Thanks to Github, making small changes is super easy. After forking the project navigate
to the file you want to change and click the edit link.

Change the file, write a commit message, and click the `Commit` button.

Now you need to get your change [accepted](#patches).
Making Documentation Changes
The compass documentation is stored in two places. First, the `doc-src` directory is
where the documentation lives -- however much of the documentation is generated
from comments in the Sass files themselves. More information on [changing
documentation][documentation]. Once your changes are pushed, please
[submit them](#patches).
Fixing Stylesheet Bugs
**Step 3**: If this is a bug you discovered. Please [report it][issues] before working on a fix.
This helps us better understand the patch.
**Step 4**: Get [the code](#setting-up-git) if you haven't yet done so.
**Step 5**: Fix the bug and commit the changes. Please make sure to mention the bug
id in your commit message like so:
Fixed the display of the fizzlebuzz in IE6.
Closes GH-123.
**Step 6**: Verify the fix in as many browsers as you can as well as against your own
project. How to [use compass while changing it](#running-local-code).
**Step 7**: Make sure the tests pass. More info on [running tests](#running-tests)
If the tests fail, fix the tests or the stylesheets accordingly. If the tests, don't
fail, that means this aspect was not well enough tested. Please [add or augment
a test](#writing-tests).
You're done. Please [submit your changes](#patches).
Making Stylesheet Changes
It is a good idea to discuss new features ideas with the compass users and developers
before building something. Please don't be shy; send an email to the [compass mailing
list](http://groups.google.com/group/compass-users).
Many feature ideas are good but not obviously a good fit for the compass core library.
In these cases, you can and should create a [compass extension][extensions]. Sometimes
this is because the concept does not align with the [compass philosophy](#project-philosophy).
But sometimes it's just because we think the idea needs time to bake. [Documentation on
making extensions.][extensions]
**Step 3**: Get [the code](#setting-up-git) if you haven't yet done so.
**Step 4**: Add the feature -- contact the mailing list if you have any questions.
**Step 5**: Add a test case. More info on [writing tests for compass](#writing-tests).
**Step 6**: Documentation - Add or update the reference documentation. Add
an example of using the feature. See the [doc readme for details][documentation].
You're done. Please [submit your changes](#patches).
Making Ruby Changes
At this time, if you're a rubyist who's planning on working on the ruby-side of
things, it's assumed you know how to read code and use standard ruby tools like
rake, gem, bundler, test/unit, cucumber, rspec, etc. If you have any questions,
please ask. No changes will be accepted without accompanying tests.
Submitting Patches
If you are submitting features that have more than one changeset, please create a
topic branch to hold the changes while they are pending merge and also to track
iterations to the original submission. To create a topic branch:
$ git checkout -b new_branch_name
... make more commits if needed ...
$ git push origin new_branch_name
You can now see these changes online at a url like:
http://github.com/your_user_name/compass/commits/new_branch_name
If you have single-commit patches, it is fine to keep them on master. But do keep in
mind that these changesets might be
[cherry-picked](#recovering-from-rebased-or-cherry-picked-changesets).
Once your changeset(s) are on github, select the appropriate branch containing your
changes and send a pull request. Make sure to choose the same upstream branch that
you developed against (probably stable or master). Most of the description of your
changes should be in the commit messages -- so no need to write a whole lot in the
pull request message. However, the pull request message is a good place to provide a
rationale or use case for the change if you think one is needed. More info on [pull
requests][pulls].

Pull requests are then managed like an issue from the [compass issues page][issues].
A code review will be performed by a compass core team member, and one of three outcomes
will result:
1. The change is rejected -- Not all changes are right for [compass's
philosophy](#project-philosophy). If your change is rejected it might be better
suited for a plugin, at least until it matures and/or proves itself with the users.
2. The change is rejected, *unless* -- Sometimes, there are missing pieces, or
other changes that need to be made before the change can be accepted. Comments
will be left on the commits indicating what issues need to be addressed.
3. The change is accepted -- The change is merged into compass, sometimes minor
changes are then applied by the committer after the merge.
Project Structure
compass/
bin/
compass - CLI executable
devbin/ - development scripts after installing the bundle
doc-src/ - source for documentation
docs/ - generated documentation
features/ - tests for compass
frameworks/ - All frameworks in this directory are loaded automatically
compass/ - The compass framework
stylesheets/ - The compass libraries
templates/ - The compass project templates and patterns
blueprint/
stylesheets/ - The blueprint libraries
templates/ - The blueprint project templates and patterns
lib/
compass.rb - The main compass ruby library
compass/
app_integration/ - integration with app frameworks
commands/ - UI agnostic support for the CLI
configuration/ - support for project configuration
exec/ - UI code for the CLI
installers/ - support for installing templates
sass_extensions/ - enhancements to Sass
functions/ - Sass functions exposed by compass
monkey_patches/ - Changes to sass itself
test/ - unit tests
General Philosophy
1. Users specify their own selectors. Compass never forces a user
to use a presentational class name.
2. Compass does not require javascript. It is a CSS framework.
3. Compass core is "design agnostic". This is why compass core has no
grid framework -- grids are not design agnostic.
4. Compass frameworks are not special. If compass can do it, so should an extension
be able.
5. Sass is awesome -- Compass should make sass more accessible and
demonstrate how to use Sass to its fullest potential.
6. Developing across browsers is hard and will always be hard. It takes
a community to get it right.
7. By default, Compass supports as many browsers as it can. Where it can't
it progressively enhances. Where it degrades, the documentation should
make a note. Deviation from this requires an excellent reason.
8. Compass is a proving ground for Sass features. The watcher and color
functions are examples of features that started in Compass and got
moved to Sass.
Stylesheet Conventions
1. All framework stylesheets are partials. Their filename begin with an underscore.
Otherwise, Sass will create stylesheets directly into the user's CSS directory.
2. Compass imports do not emit styles. There are a few limited exceptions to this like
the resets and base classes for inheritance.
3. Mixins with two-level defaults. Mixins often provide two levels of default
values. The first is a global default that can be overridden once. The second
is a default that can be overridden when the mixin is included.
4. Mixin argument names are part of the public API, make sure they are understandable and not
needlessly truncated or terse.
5. If adding a new folder of stylesheets, add a single stylesheet with the same name that
imports all of the stylesheets in the folder.
6. Try to avoid passing selectors as arguments. This is what mixins are for.
Common Problems & Miscellaneous Info
Setting up Git
Please follow [these instructions](http://help.github.com/git-email-settings/)
to set up your email address and attribution information.
Download your git repo:
git clone git@github.com:your_username/compass.git
Set up a remote to the main repo:
cd compass
git remote add chriseppstein git://github.com/chriseppstein/compass.git
Getting recent changes from the main repo:
git fetch chriseppstein
Using Compass while Under Development
1. Use the bin script. `/path/to/compass/bin/compass` is a version of the compass
command line that uses the local changes you have made. You can add `/path/to/compass/bin`
to your `$PATH`, or refer to it directly.
2. `gem build compass.gemspec`
3. `gem install compass-.gem` -- If installing to your
system gems, you'll probably need to add `sudo` to the front. If you don't know
what that means, you probably need to add `sudo` to the front.
4. In a [bundled][bundler] environment, you can configure your gem to use compass
while you work on it like so: `gem 'compass', :path => "/Users/myusername/some/path/to/compass"`
Bundler will perform some sort of charm on ruby to make it work.
5. Configuring ruby directly. If you're a ruby pro, you probably don't need to be
told that you can set compass on the load path like so: `export RUBYLIB=/Users/myusername/some/path/to/compass/lib`
Running Tests
1. You must have Ruby installed on your system. After [setting up git](#setting-up-git),
change to the root directory of your git checkout of Compass.
`cd compass`
2. Install the bundler Ruby gem.
`gem install bundler`
If installing to your system gems, you'll probably need to add `sudo` to the
front of that command. If you don't know what that means, you probably need
to add `sudo` to the front.
3. Install development dependencies:
`bundle install --binstubs devbin`
4. Running core library and stylesheet tests:
`bundle exec rake test features`
5. Running behavior tests
`./devbin/cucumber`
If stylesheet tests fail, the output of the test project is captured in
`test/fixtures/stylesheets//saved/` and the error message will report where
the error was. Here's an example:

Writing Stylesheet Tests
Compass has stylesheet tests to ensure that:
- each stylesheet compiles
- each stylesheet can be imported directly without any other dependencies
- refactorings that should not affect the output, don't
At some point, it would be great to have a test system that verifies that the stylesheets
*work correctly* in various browsers. If you have ideas for how to accomplish this in a sane
way, please let us know.
In the `test/fixtures/stylesheets` directory, there are a number of compass projects.
The tests work by adding or updating the sass files, running the tests to make sure they fail,
and then changing the expected css output to make the test pass. It is rudimentary, but as
a safety net, it has caught a number of problems that might have been missed otherwise.
If you add a new stylesheet to compass, please make sure to add a new test stylesheet
that only imports the newly added stylesheet and add rules that use the new features in that
stylesheet.
You cherry-picked/rebased
my changes. What should I do?
Depending on any number of reasons, including but not limited to the alignment of the stars,
Your changes might not be merged into compass using a simple merge. For instance, we might
decide to place a change against master into stable instead, or we might squish all your
changes together into a single commit at the time of merge, or we might want a change you've
submitted but not a change that it was placed onto top of. In these cases, there are
a couple of ways you can react:
1. If you have some changes on a branch that were not yet accepted, but other changes on that
branch were accepted then you should run the following command (make sure to fetch first):
`git checkout branch_name; git rebase chriseppstein/master` (assuming the change was applied
to the master branch)
2. If all your changes on the topic branch were accepted or you don't care to keep it around
anymore: `git checkout master; git branch -D branch_name; git push origin :branch_name`
[pulls]: http://help.github.com/pull-requests/
[issues]: http://github.com/chriseppstein/compass/issues
[documentation]: http://github.com/chriseppstein/compass/blob/stable/doc-src/README.markdown
[bundler]: http://gembundler.com/
[extensions]: /help/tutorials/extensions/
================================================
FILE: Guardfile
================================================
group :tests do
guard :test do
watch(%r{^lib/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
watch(%r{^test/.+_test\.rb$})
watch(%r{^test/units/.+_test\.rb$})
watch('test/test_helper.rb') { "test" }
end
end
group :features do
guard :cucumber do
watch(%r{^features/.+\.feature$})
watch(%r{^features/support/.+$}) { 'features' }
watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
end
end
================================================
FILE: LICENSE.markdown
================================================
Copyright (c) 2009-2014 Christopher M. Eppstein
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
No attribution is required by products that make use of this software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name(s) of the above copyright
holders shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written authorization.
Contributors to this project agree to grant all rights to the copyright
holder of the primary product. Attribution is maintained in the source
control history of the product.
================================================
FILE: README.markdown
================================================
# Compass Stylesheet Authoring Framework
**Depreciated:** Compass is no longer supported.
Build Status: [](https://travis-ci.org/Compass/compass)
Code Quality: [](https://codeclimate.com/github/Compass/compass)
## Resources
* [Compass Homepage](http://compass-style.org/)
* [Installing Compass](http://compass-style.org/install/)
* [Compass Reference](http://compass-style.org/install/reference/)
## Author
Compass is written by [Chris Eppstein](http://chriseppstein.github.io/).
Chris is a software engineer at [LinkedIn](http://www.linkedin.com/) and a member of the [Sass](https://github.com/nex3/sass) core team.
## Core Team Members
* [Scott Davis](https://github.com/scottdavis)
* [Miriam Suzanne](https://github.com/mirisuzanne)
* [Brandon Mathis](https://github.com/imathis)
## Major Contributors
* [Nico Hagenburger](https://github.com/hagenburger)
## License
Copyright (c) 2008-2014 Christopher M. Eppstein
All Rights Reserved.
Released under a [slightly modified MIT License](LICENSE.markdown).
================================================
FILE: Rakefile
================================================
GEMS = ['core', 'cli', 'import-once']
task :default => %w[test]
desc "Run all tests"
task :test do
sh %{./test_all.sh} do |ok, res|
Rake::Task["test_cleanup"].invoke if ok
end
end
desc "build gems"
task :build_gems => [:test] do
GEMS.each do |gem|
chdir gem do
if gem == 'cli'
sh "gem build compass.gemspec"
else
sh "gem build compass-#{gem}.gemspec"
end
end
end
end
desc "publish gems"
task :publish_gems => [:build_gems] do
GEMS.each do |gem|
chdir gem do
if gem == 'cli'
sh "gem push compass.gemspec"
else
sh "gem push compass-#{gem}.gemspec"
end
end
end
end
desc "Clean up all test files"
task :test_cleanup do
dirs = [
'core/devbin/',
'core/.sass-cache/',
'core/test/integrations/projects/busted_font_urls/tmp/',
'core/test/integrations/projects/busted_image_urls/tmp/',
'core/test/integrations/projects/compass/tmp/',
'core/test/integrations/projects/envtest/tmp/',
'core/test/integrations/projects/image_urls/tmp/',
'core/test/integrations/projects/relative/tmp/',
'core/test/integrations/projects/uses_only_stylesheets_ext/tmp/',
'core/test/integrations/projects/valid/tmp/',
'import-once/.sass-cache/'
]
dirs.each { |dir| rm_rf dir }
end
desc "Bundle Update"
task :bundle_update do
GEMS.each do |gem|
chdir gem do
sh "bundle update"
end
end
end
================================================
FILE: TODO.md
================================================
FYI: I'm abandoning the even/odd release numbering scheme in favor of using preview releases. Going forward the master branch will use the following release numbering:
* 0.11.0.alpha.N.shortsha (Not tagged)
* 0.11.0.beta.N (tagged, new features expected)
* 0.11.0.rc.N (tagged, no new features expected)
MUST:
* A proper welcome page for blueprint projects (or delete it)
* Rails Integration
NICE:
* some extension commands
* Better help for commands and patterns
* Color Palette extraction and management commands
v0.11
=====
Planned Release Date: Aug 2, 2010
This is a quick iteration release. The focus on turning out
even better documentation and some stylesheet updates and
enhancements that take better advantage of the Sass 3 features.
### Docs (can be done on stable)
* Improve the design
* Better tutorials and getting started guides.
* Terminal for Designers
* Better examples & example navigation
* Contribution guide:
* Compass stylesheets
* Compass ruby code
* Documentation patches
* SCSS Style Guide
* Bundler 1.0 support
* Upgrade nanoc
* Better search experience
* Search mixins and constants and code fragments that might use those.
* Awesome homepage that is better integrated with the docs.
* HTML5 the docs so they can run locally in offline mode.
### Compass Core
* Updates as necessary to the CSS3 module as the spec process develops.
* Typography module
### Blueprint
* Provide an option to use @extend in the blueprint grid
### Rails
* Fully integrated support of Rails 3
### Other
* Consider adding app integration with: Node.js, Django, Drupal, Wordpress
(Wherever opinionated layouts exist). Also, try to make one of these a plugin
to test out the concept.
* clean up all the argument names in preparation for keyword argument support from sass.
v0.12
=====
This release depends on Sass 3.2 and is aimed at taking advantage of
the new sass 3.2 feature set as well as really making the extensions
system come alive. Since I don't foresee any deprecations in Sass 3.2,
this will not be a coordinated release. Instead, this release will
trail Sass 3.2 by a month or two.
### Compass Core
* Figure out what to do about multiple attribute properties like background.
Might require list and function support from sass.
### Blueprint
* If sass 3.2 is out with @function support, use that for grid
calculations, otherwise punt to 1.0.
### Extensions
* Extension registry on compass-style.org.
* One step publishing via github + webhooks
* Easy install via CLI
* Local (per-user) extension repo with auto-discovery.
* Video showing how easy it is to create, publish, and install an extension.
v1.0 - Polaris
==============
### Blueprint
* If the @extend version of the grid is full of win, make it the default.
### Sassdoc
Extract the compass documentation system into a stand-alone project.
### Extensions
* Build basic docs and host them for all extensions using sassdoc.
* Support for selling extensions and taking a cut for umdf.org?
### Project Tools
* enable building project docs using the sassdoc tool.
v2.0
====
Version 2 is all about making compass easier to use. Compass and Sass
will have a GUI that makes it simple to manage your projects.
### GUI Prerelease 1
* Concept brainstorming
* mockups
* How can compass gui and sass gui interoperate or plug in.
### GUI Prerelease 2
Beta release as a separate install.
### GUI Prerelease 3
* Iterate based on feedback.
* Integrate with a Sass GUI.
* Embed the docs
### One-click Installers
Install compass and sass with one click
* Windows (Only if someone else wants to build and maintain it.)
* Mac (.dmg + drag & drop app or installer)
* Linux (Get distro packages going and in place for the 1.0 release)
================================================
FILE: cli/.gitignore
================================================
*.DS_Store
*.tmproj
*.lock
tmp/*
devbin
.sass-cache
test/tmp
test/fixtures/stylesheets/*/tmp
test/fixtures/stylesheets/*/saved
test/fixtures/stylesheets/empty
test/fixtures/stylesheets/*/sass/.sass-cache
test/fixtures/stylesheets/valid/css/*
pkg/*
compass-*.gem
coverage*
docs
.bundle
attic
devbin
.rvmrc
*.rbc
vendor/ruby
vendor
Gemfile.lock
*.pkg
RELEASE_VERSION
================================================
FILE: cli/Gemfile
================================================
source 'https://rubygems.org'
gemspec unless defined?(CI)
unless ENV['PKG']
gem "sass", "~> 3.3.13" unless defined?(CI)
gem "compass-core", :path => "../core" unless defined?(CI)
gem "compass-import-once", :path => "../import-once" unless defined?(CI)
gem 'sass-globbing', "~> 1.1.1"
gem "cucumber", "~> 1.2.1"
gem "rspec", "~> 2.0.0"
gem "compass-validator", "3.0.1"
gem "css_parser", "~> 1.0.1"
gem "rubyzip", "0.9.9"
gem 'mocha', '0.11.4'
gem 'minitest', '2.12.1'
gem 'diff-lcs', '~> 1.1.2'
gem 'rake'
gem 'json', '~> 1.7.7', :platforms => :ruby_18
gem 'true', "~> 0.2.3"
gem 'test-unit', '~> 3.0.9'
# Warning be carful adding OS dependant gems above this line it will break the CI server please
# place them below so they are excluded
unless ENV["CI"]
gem 'rb-fsevent'
gem 'ruby_gntp'
gem "ruby-prof", :platforms => [:mri_19, :mri_20]
gem "rcov", :platforms => :mri_18
gem 'guard', :platforms => [:mri_20]
gem 'guard-test', :platforms => [:mri_20]
gem 'guard-cucumber', :platforms => [:mri_20]
# gem 'packager'
gem 'colorize'
gem 'pry'
end
end
================================================
FILE: cli/Rakefile
================================================
sh "git checkout lib/compass/generated_version.rb"
require 'rubygems'
require 'rubygems/package_task'
require 'rake/testtask'
require 'fileutils'
if ENV["PKG"]
$: << File.expand_path(File.dirname(__FILE__))+"/lib"
else
require 'bundler/setup'
end
unless ENV['CI']
require 'colorize'
require 'fileutils'
end
begin
require 'rake/dsl_definition'
rescue LoadError
# pass
end
# ----- Default: Testing ------
task :default => [:test, :features]
begin
require 'cucumber'
require 'cucumber/rake/task'
Cucumber::Rake::Task.new(:features) do |t|
#t.cucumber_opts = %w{--format progress}
end
rescue LoadError
$stderr.puts "cannot load cucumber"
end
Rake::TestTask.new :test do |t|
t.libs << 'lib'
t.libs << 'test'
test_files = FileList['test/**/*_test.rb']
test_files.exclude('test/rails/*', 'test/haml/*')
t.test_files = test_files
t.verbose = true
end
Rake::TestTask.new :units do |t|
t.libs << 'lib'
t.libs << 'test'
test_files = FileList['test/units/**/*_test.rb']
test_files.exclude('test/rails/*', 'test/haml/*')
t.test_files = test_files
t.verbose = true
end
Rake::TestTask.new :integrations do |t|
t.libs << 'lib'
t.libs << 'test'
test_files = FileList['test/integrations/**/*_test.rb']
test_files.exclude('test/rails/*', 'test/haml/*')
t.test_files = test_files
t.verbose = true
end
namespace :git do
task :clean do
sh "git", "clean", "-fdx"
end
end
begin
require 'cucumber/rake/task'
require 'rcov/rcovtask'
namespace :rcov do
Cucumber::Rake::Task.new(:cucumber) do |t|
t.rcov = true
t.rcov_opts = %w{--exclude osx\/objc,gems\/,spec\/,features\/ --aggregate coverage.data}
t.rcov_opts << %[-o "coverage"]
end
Rcov::RcovTask.new(:units) do |rcov|
rcov.libs << 'lib'
test_files = FileList['test/**/*_test.rb']
test_files.exclude('test/rails/*', 'test/haml/*')
rcov.pattern = test_files
rcov.output_dir = 'coverage'
rcov.verbose = true
rcov.rcov_opts = %w{--exclude osx\/objc,gems\/,spec\/,features\/ --aggregate coverage.data}
rcov.rcov_opts << %[-o "coverage" --sort coverage]
end
desc "Run both specs and features to generate aggregated coverage"
task :all do |t|
rm "coverage.data" if File.exist?("coverage.data")
Rake::Task["rcov:units"].invoke
Rake::Task["rcov:cucumber"].invoke
end
end
rescue LoadError => e
puts "WARNING: #{e}"
end
namespace :test do
debug = false
desc "update test expectations if needed"
task :update do
Rake::Task['test:update:fixtures'].invoke
end
task :debug do
debug = true
Rake::Task['test:update:fixtures'].invoke
end
namespace :update do
EXPECTED = 'css'
TMP = 'tmp'
#desc "update fixture expectations for test cases if needed"
task :fixtures do
fixtures = File.join('test/fixtures/stylesheets/compass'.split('/'))
# remove any existing temporary files
FileUtils.rm_rf(File.join(File.dirname(__FILE__), fixtures, TMP, '.'))
# compile the fixtures
puts "checking test cases..."
CHECKMARK = "\u2713 "
filter = debug ? '--trace' : "| grep 'error.*#{fixtures}'"
errors = %x[compass compile #{fixtures} #{filter}]
# check for compilation errors
if not errors.empty?
puts "Please fix the following errors before proceeding:".colorize(:red) if not debug
puts errors
else
# check to see what's changed
diff = %x[diff -r #{File.join(fixtures, EXPECTED, '')} #{File.join(fixtures, TMP, '')}]
# ignore non-CSS files in css/
diff.gsub!(/^Only in .*\/css\/(.*)\:.*[^.]/, '')
if diff.empty?
puts "#{CHECKMARK}Cool! Looks like all the tests are up to date".colorize(:green)
else
puts "The following changes were found:"
puts "===================================="
# check for new or removed expectations
diff.scan(/^Only in .*\/(#{EXPECTED}|#{TMP})\/(.*)\: (.*).css/).each do |match|
config = (match[0] == TMP) ? [:green, '>', 'NEW TEST'] : [:red, '<', 'DELETED']
puts "[#{File.join(match[1], match[2])}] #{config[2].colorize(config[0])}".colorize(:cyan)
new_file = File.join(File.dirname(__FILE__), fixtures, match[0], match[1], match[2]) + '.css'
puts File.read(new_file).gsub(/^(.*)/, config[1] + ' \1').colorize(config[0])
end
diff = diff.gsub(/^diff\s\-r\s.*\/tmp\/(.*).css/, '[\1]'.colorize(:cyan))
diff = diff.gsub(/^Only in .*\n?/, '')
diff = diff.gsub(/^(\<.*)/, '\1'.colorize(:red))
diff = diff.gsub(/^(\>.*)/, '\1'.colorize(:green))
diff = diff.gsub(/^(\d+.*)/, '\1'.colorize(:cyan))
puts diff
puts "===================================="
puts "Are all of these changes expected? [y/n]".colorize(:yellow)
if (($stdin.gets.chomp)[0] == 'y')
FileUtils.rm_rf(File.join(File.dirname(__FILE__), fixtures, EXPECTED, '.'))
FileUtils.cp_r(File.join(File.dirname(__FILE__), fixtures, TMP, '.'), File.join(File.dirname(__FILE__), fixtures, EXPECTED))
puts "#{CHECKMARK}Thanks! The test expectations have been updated".colorize(:green)
else
puts "Please manually update the test cases and expectations".colorize(:red)
end
end
end
end
end
end
# Release tasks
gemspec_file = FileList['compass.gemspec'].first
spec = eval(File.read(gemspec_file), binding, gemspec_file)
spec.files.delete("VERSION")
spec.files.delete("VERSION_NAME")
def spec.bump!
segments = version.to_s.split(".")
segments[-1] = segments.last.succ
self.version = Gem::Version.new(segments.join("."))
end
# Set SAME_VERSION when moving to a new major version and you want to specify the new version
# explicitly instead of bumping the current version.
# E.g. rake build SAME_VERSION=true
spec.bump! unless ENV["SAME_VERSION"]
desc "Run tests and build compass-#{spec.version}.gem"
task :build => [:default, :gem]
task :gem => :release_version
task :release_version do
open("lib/compass/generated_version.rb", "w") do |f|
f.write(< [:record_version, :push_gem, :tag]
desc "Build & Publish version #{spec.version}"
task :release => [:build, :publish]
Gem::PackageTask.new(spec) do |pkg|
pkg.need_zip = true
pkg.need_tar = true
end
desc "Record the new version in version control for posterity"
task :record_version do
unless ENV["SAME_VERSION"]
open(FileList["VERSION"].first, "w") do |f|
f.write(spec.version.to_s)
end
sh "git add VERSION"
sh "git checkout lib/compass/generated_version.rb"
sh %Q{git commit -m "Bump version to #{spec.version}."}
end
end
desc "Tag the repo as #{spec.version} and push the code and tag."
task :tag do
sh "git tag -a -m 'Version #{spec.version}' #{spec.version}"
sh "git push --tags origin #{`git rev-parse --abbrev-ref HEAD`}"
end
desc "Push compass-#{spec.version}.gem to the rubygems server"
task :push_gem do
sh "gem push pkg/compass-#{spec.version}.gem"
end
================================================
FILE: cli/VERSION
================================================
1.0.3
================================================
FILE: cli/VERSION_NAME
================================================
Polaris
================================================
FILE: cli/bin/compass
================================================
#!/usr/bin/env ruby
# The compass command line utility
# This allows compass to run easily from a git checkout without install.
def fallback_load_path(path)
retried = false
begin
yield
rescue LoadError
unless retried
$: << path
retried = true
retry
end
raise
end
end
fallback_load_path(File.join(File.dirname(__FILE__), '..', 'lib')) do
require 'compass'
require 'compass/exec'
end
if defined?(Bundler)
require 'bundler/shared_helpers'
Bundler.require :assets if Bundler::SharedHelpers.in_bundle?
end
runner = Proc.new do
Compass::Exec::SubCommandUI.new(ARGV).run!
end
if ARGV.delete("--profile")
require 'ruby-prof'
RubyProf.start
exit_code = runner.call
result = RubyProf.stop
# Print a flat profile to text
printer = RubyProf::FlatPrinter.new(result)
printer.print(STDERR, 0)
exit exit_code
else
exit runner.call || 1
end
================================================
FILE: cli/compass.gemspec
================================================
path = File.expand_path("lib", File.dirname(__FILE__))
$:.unshift(path) unless $:.include?(path)
require 'compass/version'
Gem::Specification.new do |gemspec|
gemspec.name = "compass"
gemspec.version = Compass::VERSION # Update VERSION file to set this.
gemspec.description = "Compass is a Sass-based Stylesheet Framework that streamlines the creation and maintenance of CSS."
gemspec.homepage = "http://compass-style.org"
gemspec.authors = ["Chris Eppstein", "Scott Davis", "Eric M. Suzanne", "Brandon Mathis", "Nico Hagenburger"]
gemspec.email = "chris@eppsteins.net"
gemspec.executables = %w(compass)
gemspec.require_paths = %w(lib)
gemspec.rubygems_version = "1.3.5"
gemspec.summary = %q{A Real Stylesheet Framework}
gemspec.add_dependency 'sass', '>= 3.3.13', '< 3.5'
gemspec.add_dependency 'compass-core', "~> #{File.read(File.join(File.dirname(__FILE__),"..","core","VERSION")).strip}"
gemspec.add_dependency 'compass-import-once', "~> #{File.read(File.join(File.dirname(__FILE__),"..","import-once","VERSION")).strip}"
gemspec.add_dependency 'chunky_png', '~> 1.2'
gemspec.add_dependency 'rb-fsevent', '>= 0.9.3'
gemspec.add_dependency 'rb-inotify', '>= 0.9'
gemspec.post_install_message = <<-MESSAGE
Compass is charityware. If you love it, please donate on our behalf at http://umdf.org/compass Thanks!
MESSAGE
gemspec.files = %w(LICENSE.markdown VERSION VERSION_NAME Rakefile)
gemspec.files += Dir.glob("bin/*")
gemspec.files += Dir.glob("data/**/*")
gemspec.files += Dir.glob("frameworks/**/*")
gemspec.files += Dir.glob("lib/**/*")
gemspec.files += Dir.glob("test/**/*.*")
gemspec.files -= Dir.glob("test/fixtures/stylesheets/*/saved/**/*.*")
gemspec.test_files = Dir.glob("test/**/*.*")
gemspec.test_files -= Dir.glob("test/fixtures/stylesheets/*/saved/**/*.*")
gemspec.test_files += Dir.glob("features/**/*.*")
end
================================================
FILE: cli/features/command_line.feature
================================================
Feature: Command Line
In order to manage my stylesheets
As a user on the command line
I want to create a new project
Scenario: Install a project without a framework
When I create a project using: compass create my_project
Then a directory my_project/ is created
And a configuration file my_project/config.rb is created
And a sass file my_project/sass/screen.scss is created
And a sass file my_project/sass/print.scss is created
And a sass file my_project/sass/ie.scss is created
And a css file my_project/stylesheets/screen.css is created
And a css file my_project/stylesheets/print.css is created
And a css file my_project/stylesheets/ie.css is created
And I am told how to link to /stylesheets/screen.css for media "screen, projection"
And I am told how to link to /stylesheets/print.css for media "print"
And I am told how to conditionally link "IE" to /stylesheets/ie.css for media "screen, projection"
Scenario: Install a project with specific directories
When I create a project using: compass create custom_project --using compass --sass-dir sass --css-dir css --images-dir assets/imgs
Then a directory custom_project/ is created
And a directory custom_project/sass/ is created
And a directory custom_project/css/ is created
And a sass file custom_project/sass/screen.scss is created
And a css file custom_project/css/screen.css is created
Scenario: Creating a bare project
When I create a project using: compass create bare_project --bare
Then a directory bare_project/ is created
And a configuration file bare_project/config.rb is created
And a directory bare_project/sass/ is created
And a directory bare_project/stylesheets/ is not created
And I am congratulated
And I am told that I can place stylesheets in the sass subdirectory
And I am told how to compile my sass stylesheets
Scenario: Compiling a project with errors
Given I am using the existing project in test/fixtures/stylesheets/valid
And the project has a file named "sass/error.scss" containing:
"""
.broken {
"""
When I run: compass compile
Then the command exits with a non-zero error code
Scenario: Creating a bare project with a framework
When I create a project using: compass create bare_project --using blueprint --bare
Then an error message is printed out: A bare project cannot be created when a framework is specified.
And the command exits with a non-zero error code
Scenario: Compiling an existing project.
Given I am using the existing project in test/fixtures/stylesheets/valid
When I run: compass compile
Then a directory tmp/ is created
And a css file tmp/simple.css is created
Scenario: Compiling an existing project with a specified project
Given I am using the existing project in test/fixtures/stylesheets/valid
And I am in the parent directory
When I run: compass compile tmp_valid
Then a directory tmp_valid/tmp/ is created
And a css file tmp_valid/tmp/simple.css is created
Scenario: Recompiling a project with no changes
Given I am using the existing project in test/fixtures/stylesheets/valid
When I run: compass compile
And I run: compass compile
Scenario: compiling a specific file in a project
Given I am using the existing project in test/fixtures/stylesheets/valid
And I run: compass compile sass/simple.sass
Then a sass file sass/another_simple.scss is not mentioned
And a css file tmp/simple.css is reported written
And a css file tmp/simple.css is created
And a css file tmp/another_simple.css is not created
Scenario: Re-compiling a specific file in a project with no changes
Given I am using the existing project in test/fixtures/stylesheets/valid
When I run: compass compile
And I run: compass compile sass/simple.sass --force
Then a sass file sass/another_simple.scss is not mentioned
And a css file tmp/simple.css is reported written
Scenario: Basic help
When I run: compass help
Then I should see the following "primary" commands:
| clean |
| compile |
| create |
| init |
| watch |
And I should see the following "other" commands:
| config |
| extension |
| frameworks |
| help |
| imports |
| install |
| interactive |
| sprite |
| stats |
| unpack |
| validate |
| version |
Scenario: Recompiling a project with no material changes
Given I am using the existing project in test/fixtures/stylesheets/valid
When I run: compass compile
And I wait 1 second
And I touch sass/simple.sass
And I run: compass compile
Then a css file tmp/simple.css is reported written
Scenario: Recompiling a project with changes
Given I am using the existing project in test/fixtures/stylesheets/valid
When I run: compass compile
And I wait 1 second
And I add some sass to sass/simple.sass
And I run: compass compile
And a css file tmp/simple.css is reported written
Scenario: Cleaning a project
Given I am using the existing project in test/fixtures/stylesheets/valid
When I run: compass compile
And I run: compass clean
Then the following files are reported removed:
| .sass-cache/ |
| tmp/simple.css |
| tmp/another_simple.css |
And the following files are removed:
| .sass-cache/ |
| tmp/simple.css |
| tmp/another_simple.css |
@now
Scenario: Watching a project for changes
Given ruby supports fork
Given I am using the existing project in test/fixtures/stylesheets/valid
When I run: compass compile
And I run in a separate process: compass watch
And I wait 4 seconds
And I touch sass/simple.sass
And I wait 2 seconds
And I shutdown the other process
Then a css file tmp/simple.css is reported written
Scenario: Generate a compass configuration file
Given I should clean up the directory: config
When I run: compass config config/compass.rb --sass-dir sass --css-dir assets/css
Then a configuration file config/compass.rb is created
And the following configuration properties are set in config/compass.rb:
| property | value |
| sass_dir | sass |
| css_dir | assets/css |
Scenario Outline: Print out a configuration value
Given I am using the existing project in test/fixtures/stylesheets/valid
When I run: compass config -p
Then I should see the following output:
And the command exits
Examples:
| property | value | exit |
| extensions_dir | extensions | normally |
| extensions_path | $PROJECT_PATH/extensions | normally |
| css_dir | tmp | normally |
| css_path | $PROJECT_PATH/tmp | normally |
| sass_dir | sass | normally |
| sass_path | $PROJECT_PATH/sass | normally |
| foobar | ERROR: configuration property 'foobar' does not exist | with a non-zero error code |
@validator
Scenario: Validate the generated CSS
Given I am using the existing project in test/fixtures/stylesheets/valid
When I run: compass validate
Then my css is validated
And I am informed that my css is valid.
@stats
Scenario: Get stats for my project
Given I am using the existing project in test/fixtures/stylesheets/valid
When I run: bundle exec compass stats
Then I am told statistics for each file:
| Filename | Rules | Properties | Mixins Defs | Mixins Used | Filesize | CSS Selectors | CSS Properties | CSS Filesize |
| sass/simple.sass | \d+ | \d+ | \d+ | \d+ | \d+ K?B | \d+ | \d+ | \d+ K?B |
| sass/another_simple.scss | \d+ | \d+ | \d+ | \d+ | \d+ K?B | \d+ | \d+ | \d+ K?B |
| Total.* | \d+ | \d+ | \d+ | \d+ | \d+ K?B | \d+ | \d+ | \d+ K?B |
@listframeworks
Scenario: List frameworks registered with compass
When I run: compass frameworks
Then I should see the following lines of output:
| compass |
================================================
FILE: cli/features/extensions.feature
================================================
Feature: Extensions
In order to have an open source ecosystem for stylesheets
As a compass user
I can install extensions that others have created
And I can create and publish my own extensions
@listframeworks
Scenario: Extensions directory for stand_alone projects
Given I am using the existing project in test/fixtures/stylesheets/compass
And the "extensions" directory exists
And and I have a fake extension at extensions/testing
When I run: compass frameworks
Then the list of frameworks includes "testing"
@listframeworks
Scenario: Shared extensions directory
Given the "~/.compass/extensions" directory exists
And and I have a fake extension at ~/.compass/extensions/testing
And I am using the existing project in test/fixtures/stylesheets/compass
When I run: compass frameworks
Then the list of frameworks includes "testing"
@listframeworks
Scenario: Frameworks without templates
Given I am using the existing project in test/fixtures/stylesheets/uses_only_stylesheets_ext
When I run: compass frameworks
Then the list of frameworks includes "only_stylesheets"
================================================
FILE: cli/features/step_definitions/command_line_steps.rb
================================================
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '../../test')))
require 'bundler/setup'
require 'test_helper'
require 'compass/exec'
include Compass::TestCaseHelper
include Compass::CommandLineHelper
include Compass::IoHelper
Before do
Compass.reset_configuration!
@cleanup_directories = []
@original_working_directory = Dir.pwd
end
After do
Dir.chdir @original_working_directory
@cleanup_directories.each do |dir|
FileUtils.rm_rf dir
end
end
Given "ruby supports fork" do
if RUBY_PLATFORM == "java"
pending
end
end
# Given Preconditions
Given %r{^I am using the existing project in ([^\s]+)$} do |project|
tmp_project = "tmp_#{File.basename(project)}"
@cleanup_directories << tmp_project
FileUtils.cp_r project, tmp_project
Dir.chdir tmp_project
end
Given %r{^I am in the parent directory$} do
Dir.chdir ".."
end
Given /^I should clean up the directory: (\w+)$/ do |directory|
@cleanup_directories << directory
end
Given %r{^the project has a file named "([^"]*)" containing:$} do |arg1, string|
File.open(arg1, "w") do |f|
f << string
end
end
# When Actions are performed
When /^I create a project using: compass create ([^\s]+) ?(.+)?$/ do |dir, args|
@cleanup_directories << dir
compass 'create', dir, *(args || '').split
end
When /^I initialize a project using: compass init ?(.+)?$/ do |args|
compass 'init', *(args || '').split
end
When /^I run: compass ([^\s]+) ?(.+)?$/ do |command, args|
compass command, *(args || '').split
end
When /^I run in a separate process: compass ([^\s]+) ?(.+)?$/ do |command, args|
unless @other_process = fork
@last_result = ''
@last_error = ''
Signal.trap("HUP") do
open('/tmp/last_result.compass_test.txt', 'w') do |file|
file.puts $stdout.string
end
open('/tmp/last_error.compass_test.txt', 'w') do |file|
file.puts $stderr.string
end
exit!
end
# this command will run forever
# we kill it with a HUP signal from the parent process.
args = (args || '').split
args << { :wait => 5 }
compass command, *args
exit!
end
end
When /^I shutdown the other process$/ do
Process.kill("HUP", @other_process)
Process.wait
@last_result = File.read('/tmp/last_result.compass_test.txt')
@last_error = File.read('/tmp/last_error.compass_test.txt')
end
When /^I touch ([^\s]+)$/ do |filename|
FileUtils.touch filename
end
When /^I wait ([\d.]+) seconds?$/ do |count|
sleep count.to_f
end
When /^I add some sass to ([^\s]+)$/ do |filename|
open(filename, "w+") do |file|
file.puts ".added .some .arbitrary"
file.puts " sass: code"
end
end
# Then postconditions
Then /^a directory ([^ ]+) is (not )?created$/ do |directory, negated|
File.directory?(directory).should == !negated
end
Then /an? \w+ file ([^ ]+) is (not )?removed/ do |filename, negated|
File.exists?(filename).should == !!negated
end
Then /an? \w+ file ([^ ]+) is (not )?created/ do |filename, negated|
File.exists?(filename).should == !negated
end
Then "the following files are reported removed:" do |table|
table.rows.each do |css_file|
#need to find a better way but this works for now
step %Q{a css file #{css_file.first} is reported removed}
end
end
Then "the following files are removed:" do |table|
table.rows.each do |css_file|
step %Q{a css file #{css_file.first} is removed}
end
end
Then /an? \w+ file ([^ ]+) is reported removed/ do |filename|
@last_result.should =~ /delete.*#{Regexp.escape(filename)}/
end
Then /an? \w+ file ([^ ]+) is reported written/ do |filename|
@last_result.should =~ /write.*#{Regexp.escape(filename)}/
end
Then /a \w+ file ([^ ]+) is (?:reported )?compiled/ do |filename|
@last_result.should =~ /compile.*#{Regexp.escape(filename)}/
end
Then /a \w+ file ([^ ]+) is reported unchanged/ do |filename|
@last_result.should =~ /unchanged.*#{Regexp.escape(filename)}/
end
Then /a \w+ file ([^ ]+) is reported identical/ do |filename|
@last_result.should =~ /identical.*#{Regexp.escape(filename)}/
end
Then /a \w+ file ([^ ]+) is reported overwritten/ do |filename|
@last_result.should =~ /overwrite.*#{Regexp.escape(filename)}/
end
Then /a \w+ file ([^ ]+) is not mentioned/ do |filename|
@last_result.should_not =~ /#{Regexp.escape(filename)}/
end
Then /I am told how to link to ([^ ]+) for media "([^"]+)"/ do |stylesheet, media|
@last_result.should =~ %r{}
end
Then /I am told how to conditionally link "([^"]+)" to ([^ ]+) for media "([^"]+)"/ do |condition, stylesheet, media|
@last_result.should =~ %r{}mi
end
Then /^an error message is printed out: (.+)$/ do |error_message|
@last_error.should =~ Regexp.new(Regexp.escape(error_message))
end
Then /^the command exits with a non\-zero error code$/ do
@last_exit_code.should_not == 0
end
Then /^the command exits normally$/ do
@last_exit_code.should == 0
end
Then /^I am congratulated$/ do
@last_result.should =~ /Congratulations!/
end
Then /^I am told that I can place stylesheets in the ([^\s]+) subdirectory$/ do |subdir|
@last_result.should =~ /You may now add sass stylesheets to the #{subdir} subdirectory of your project./
end
Then /^I am told how to compile my sass stylesheets$/ do
@last_result.should =~ /You must compile your sass stylesheets into CSS when they change.\nThis can be done in one of the following ways:/
end
Then /^I should be shown a list of "([^"]+)" commands$/ do |kind|
@last_result.should =~ /^#{kind.capitalize} Commands:$/
@last_command_list = []
found = false
indent = nil
@last_result.split("\n").each do |line|
if line =~ /^#{kind.capitalize} Commands:$/
found = true
elsif found && line =~ /^\s+/
@last_command_list << line
elsif found && line =~ /^$|^\w/
break
end
end
end
Then /^the list of commands should describe the ([^ ]+) command$/ do |command|
@last_result.should =~ /^\s+\* #{command}\s+- [A-Z].+$/
end
Then /^the following configuration properties are set in ([^ ]+):$/ do |config_file, table|
config = Compass::Configuration::FileData.new_from_file(config_file)
table.hashes.each do |hash|
config.send(hash['property']).should == hash['value']
end
end
Then /^my css is validated$/ do
if @last_error =~ /The Compass CSS Validator could not be loaded/
pending "Missing Dependency: sudo gem install compass-validator"
else
@last_result.should =~ /files? validated/
end
end
Then /^I am informed that my css is valid.$/ do
@last_result.should =~ /Result: Valid/
end
Then /^I am told statistics for each file:$/ do |table|
# table is a Cucumber::Ast::Table
table.raw.each do |row|
re = Regexp.new row.join(' *\| *')
@last_result.should =~ re
end
end
Then /^I should see the following "([^"]+)" commands:$/ do |kind, table|
step %Q{I should be shown a list of "#{kind}" commands}
commands = @last_command_list.map{|c| c =~ /^\s+\* ([^ ]+)\s+- [A-Z].+$/; [$1]}
table.diff!(commands)
end
Then /^the image ([^ ]+) has a size of (\d+)x(\d+)$/ do |file, width, height|
# see http://snippets.dzone.com/posts/show/805
size = File.open(file, "rb") {|io| io.read}[0x10..0x18].unpack('NN')
size.should == [width.to_i, height.to_i]
end
Then /^I should see the following lines of output:$/ do |table|
table.diff!([['compass']])
end
Then /^I should see the following output: (.+)$/ do |expected|
(@last_result.strip + @last_error.strip).should == expected.gsub(/\$PROJECT_PATH/,Dir.pwd).strip
end
================================================
FILE: cli/features/step_definitions/extension_steps.rb
================================================
Given /^the "([^\"]*)" directory exists$/ do |directory|
directory.gsub!('~', ENV["HOME"]) if directory.include?('~/')
FileUtils.mkdir_p directory
end
Given /^and I have a fake extension at (.*)$/ do |directory|
directory.gsub!('~', ENV["HOME"]) if directory.include?('~/')
FileUtils.mkdir_p File.join(directory, 'stylesheets')
FileUtils.mkdir_p File.join(directory, 'templates/project')
open(File.join(directory, 'templates/project/manifest.rb'),"w") do |f|
f.puts %Q{
description "This is a fake extension"
help "this is the fake help"
welcome_message "this is a fake welcome"
}
end
end
Then /^the list of frameworks includes "([^\"]*)"$/ do |framework|
@last_result.split("\n").map{|f| f.gsub(/(^\s+[*-]\s+)|(\s+$)/,'')}.should include(framework)
end
================================================
FILE: cli/gemfiles/listen_2.gemfile
================================================
CI=true
main_gemfile = File.expand_path(File.join(File.dirname(__FILE__), "..", "Gemfile"))
eval File.read(main_gemfile), nil, main_gemfile
gem 'sass', '~> 3.3.12'
gem 'compass', :path => "../"
gem 'compass-core', :path => "../../core"
gem 'compass-import-once', :path => "../../import-once"
gem 'listen', '~> 2.7.1'
gemspec :path=>"../"
================================================
FILE: cli/gemfiles/sass_3_3.gemfile
================================================
CI=true
main_gemfile = File.expand_path(File.join(File.dirname(__FILE__), "..", "Gemfile"))
eval File.read(main_gemfile), nil, main_gemfile
gem 'sass', "~> 3.3.12"
gem 'compass', :path => "../"
gem 'compass-core', :path => "../../core"
gem 'compass-import-once', :path => "../../import-once"
gemspec :path=>"../"
================================================
FILE: cli/gemfiles/sass_local.gemfile
================================================
CI=true
main_gemfile = File.expand_path(File.join(File.dirname(__FILE__), "..", "Gemfile"))
eval File.read(main_gemfile), nil, main_gemfile
gem 'sass', :path => "../../sass"
gem 'compass', :path => "../"
gemspec :path=>"../"
================================================
FILE: cli/lib/compass/actions.rb
================================================
module Compass
module Actions
attr_writer :logger
def logger
@logger ||= ::Compass::Logger.new
end
# copy/process a template in the compass template directory to the project directory.
def copy(from, to, options = nil, binary = false)
options ||= self.options if self.respond_to?(:options)
if binary
contents = File.new(from,"rb").read
else
contents = File.new(from).read
end
write_file to, contents, options, binary
end
# create a directory and all the directories necessary to reach it.
def directory(dir, options = nil)
options ||= self.options if self.respond_to?(:options)
options ||= {}
if File.exists?(dir) && File.directory?(dir)
# do nothing
elsif File.exists?(dir)
msg = "#{basename(dir)} already exists and is not a directory."
raise Compass::FilesystemConflict.new(msg)
else
log_action :directory, separate("#{basename(dir)}/"), options
FileUtils.mkdir_p(dir)
end
end
# Write a file given the file contents as a string
def write_file(file_name, contents, options = nil, binary = false)
options ||= self.options if self.respond_to?(:options)
skip_write = false
contents = process_erb(contents, options[:erb]) if options[:erb]
if File.exists?(file_name)
existing_contents = IO.read(file_name)
if existing_contents == contents
log_action :identical, basename(file_name), options
skip_write = true
elsif options[:force]
log_action :overwrite, basename(file_name), options
else
msg = "File #{basename(file_name)} already exists. Run with --force to force overwrite."
raise Compass::FilesystemConflict.new(msg)
end
else
log_action :create, basename(file_name), options
end
if skip_write
FileUtils.touch file_name
else
mode = "w"
mode << "b" if binary
open(file_name, mode) do |file|
file.write(contents)
end
end
end
def process_erb(contents, ctx = nil)
ctx = Object.new.instance_eval("binding") unless ctx.is_a? Binding
ERB.new(contents).result(ctx)
end
def remove(file_name)
file_name ||= ''
if File.directory?(file_name)
FileUtils.rm_rf file_name
log_action :remove, basename(file_name)+"/", options
elsif File.exists?(file_name)
File.unlink file_name
log_action :remove, basename(file_name), options
end
end
def basename(file)
relativize(file) {|f| File.basename(file)}
end
def relativize(path)
path = File.expand_path(path)
if path.index(working_path+File::SEPARATOR) == 0
path[(working_path+File::SEPARATOR).length..-1]
elsif block_given?
yield path
else
path
end
end
# Write paths like we're on unix and then fix it
def separate(path)
path.gsub(%r{/}, File::SEPARATOR)
end
# Removes the trailing separator, if any, from a path.
def strip_trailing_separator(path)
(path[-1..-1] == File::SEPARATOR) ? path[0..-2] : path
end
def log_action(action, file, options)
quiet = !!options[:quiet]
quiet = false if options[:loud] && options[:loud] == true
quiet = false if options[:loud] && options[:loud].is_a?(Array) && options[:loud].include?(action)
unless quiet
logger.record(action, file, options[:extra].to_s)
end
end
end
end
================================================
FILE: cli/lib/compass/app_integration/stand_alone/configuration_defaults.rb
================================================
module Compass
module AppIntegration
module StandAlone
module ConfigurationDefaults
def default_project_type
:stand_alone
end
def sass_dir_without_default
"sass"
end
def javascripts_dir_without_default
"javascripts"
end
def css_dir_without_default
"stylesheets"
end
def images_dir_without_default
"images"
end
def default_cache_dir
".sass-cache"
end
end
end
end
end
================================================
FILE: cli/lib/compass/app_integration/stand_alone/installer.rb
================================================
module Compass
module Installers
class Base
end
class ManifestInstaller < Base
end
end
module AppIntegration
module StandAlone
class Installer < Compass::Installers::ManifestInstaller
def init
directory targetize("")
super
end
def write_configuration_files(config_file = nil)
config_file ||= targetize('config.rb')
write_file config_file, config_contents
end
def config_files_exist?
File.exists? targetize('config.rb')
end
def config_contents
project_path, Compass.configuration.project_path = Compass.configuration.project_path, nil
Compass.configuration.serialize
ensure
Compass.configuration.project_path = project_path
end
def prepare
write_configuration_files unless config_files_exist? || !@manifest.generate_config?
end
def completed_configuration
nil
end
def finalize(options = {})
if options[:create] && !manifest.welcome_message_options[:replace]
puts <<-NEXTSTEPS
*********************************************************************
Congratulations! Your compass project has been created.
You may now add and edit sass stylesheets in the #{Compass.configuration.sass_dir} subdirectory of your project.
Sass files beginning with an underscore are called partials and won't be
compiled to CSS, but they can be imported into other sass stylesheets.
You can configure your project by editing the config.rb configuration file.
You must compile your sass stylesheets into CSS when they change.
This can be done in one of the following ways:
1. To compile on demand:
compass compile [path/to/project]
2. To monitor your project for changes and automatically recompile:
compass watch [path/to/project]
More Resources:
* Website: http://compass-style.org/
* Sass: http://sass-lang.com
* Community: http://groups.google.com/group/compass-users/
NEXTSTEPS
end
puts manifest.welcome_message if manifest.welcome_message
if manifest.has_stylesheet? && !manifest.welcome_message_options[:replace]
puts "\nTo import your new stylesheets add the following lines of HTML (or equivalent) to your webpage:"
puts stylesheet_links
end
end
def compilation_required?
@manifest.compile?
end
end
end
end
end
================================================
FILE: cli/lib/compass/app_integration/stand_alone.rb
================================================
%w(configuration_defaults installer).each do |lib|
require "compass/app_integration/stand_alone/#{lib}"
end
module Compass
module AppIntegration
module StandAlone
extend self
def installer(*args)
Installer.new(*args)
end
def configuration
Compass::Configuration::Data.new('stand_alone').
extend(ConfigurationDefaults)
end
end
end
end
================================================
FILE: cli/lib/compass/app_integration.rb
================================================
require "compass/app_integration/stand_alone"
module Compass
module AppIntegration
module Helpers
#attr_accessor :project_types
DEAFULT_PROJECT_TYPES = {
:stand_alone => "Compass::AppIntegration::StandAlone"
}
def init
@project_types ||= DEAFULT_PROJECT_TYPES.dup
end
def project_types
@project_types
end
def default?
@project_types.keys === DEAFULT_PROJECT_TYPES.keys
end
def lookup(type)
unless @project_types[type].nil?
eval @project_types[type]
else
raise Compass::Error, "No application integration exists for #{type}"
end
end
def register(type, klass)
@project_types[type] = klass
end
end
extend Helpers
init
end
end
================================================
FILE: cli/lib/compass/commands/base.rb
================================================
module Compass
module Commands
class Base
def self.register(command_name)
Compass::Commands[command_name] = self
end
include Actions
attr_accessor :working_path, :options
def initialize(working_path, options)
self.working_path = working_path.to_s
self.options = options
end
def execute
perform
end
def perform
raise StandardError.new("Not Implemented")
end
def successful?
!@failed
end
def failed!
@failed = true
end
protected
def framework
unless Compass::Frameworks[options[:framework]]
raise Compass::Error.new("No such framework: #{options[:framework].inspect}")
end
Compass::Frameworks[options[:framework]]
end
end
end
end
================================================
FILE: cli/lib/compass/commands/clean_project.rb
================================================
require 'compass/commands/project_base'
require 'compass/compiler'
module Compass
module Commands
module CleanProjectOptionsParser
def set_options(opts)
opts.banner = %Q{
Usage: compass clean [path/to/project] [options]
Description:
Remove generated files and the sass cache.
Options:
}.split("\n").map{|l| l.gsub(/^ */,'')}.join("\n")
super
end
end
class CleanProject < UpdateProject
register :clean
def initialize(working_path, options)
super
assert_project_directory_exists!
end
def perform
compiler = new_compiler_instance
compiler.clean!
Compass::SpriteImporter.find_all_sprite_map_files(Compass.configuration.generated_images_path).each do |sprite|
remove sprite
end
end
def determine_cache_location
Compass.configuration.cache_path || Sass::Plugin.options[:cache_location] || File.join(working_path, ".sass-cache")
end
class << self
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(Compass::Exec::GlobalOptionsParser)
parser.extend(Compass::Exec::ProjectOptionsParser)
parser.extend(CleanProjectOptionsParser)
end
def usage
option_parser([]).to_s
end
def primary; true; end
def description(command)
"Remove generated files and the sass cache"
end
def parse!(arguments)
parser = option_parser(arguments)
parser.parse!
parse_arguments!(parser, arguments)
parser.options
end
def parse_arguments!(parser, arguments)
if arguments.size > 0
parser.options[:project_name] = arguments.shift if File.directory?(arguments.first)
unless arguments.empty?
parser.options[:sass_files] = arguments.dup
parser.options[:force] = true
end
end
end
end
end
end
end
================================================
FILE: cli/lib/compass/commands/create_project.rb
================================================
require 'fileutils'
require 'compass/commands/stamp_pattern'
module Compass
module Commands
module CreateProjectOptionsParser
def set_options(opts)
if $command == "create"
opts.banner = %Q{
Usage: compass create path/to/project [options]
Description:
Create a new compass project at the path specified.
Options:
}.split("\n").map{|l| l.gsub(/^ */,'')}.join("\n")
opts.on_tail("--bare", "Don't generate any Sass or CSS files.") do
self.options[:bare] = true
end
else
opts.banner = %Q{
Usage: compass init project_type path/to/project [options]
Description:
Initialize an existing project at the path specified.
Supported Project Types:
* rails
Options:
}.split("\n").map{|l| l.gsub(/^ */,'')}.join("\n").strip
end
opts.on("--using PATTERN", "A framework's pattern to use when creating the project.") do |framework|
framework = framework.split('/', 2)
self.options[:framework] = framework[0]
self.options[:pattern] = framework[1]
end
opts.on("-x", "--syntax SYNTAX", [:sass, :scss], "Specify the syntax to use when generating stylesheets.", "One of sass or scss. Defaults to scss.") do |syntax|
self.options[:preferred_syntax] = syntax
end
opts.on("--prepare", "Prepare the project by only creating configuration files.") do
self.options[:prepare] = true
end
super
end
end
class CreateProject < StampPattern
register :create
register :init
class << self
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(Compass::Exec::GlobalOptionsParser)
parser.extend(Compass::Exec::ProjectOptionsParser)
parser.extend(CreateProjectOptionsParser)
end
def usage
option_parser([]).to_s
end
def description(command)
if command.to_sym == :create
"Create a new compass project"
else
"Add compass to an existing project"
end
end
def primary; true; end
def parse!(arguments)
parser = option_parser(arguments)
parse_options!(parser, arguments)
parse_arguments!(parser, arguments)
if parser.options[:framework] && parser.options[:bare]
raise Compass::Error, "A bare project cannot be created when a framework is specified."
end
set_default_arguments(parser)
parser.options
end
def parse_init!(arguments)
parser = option_parser(arguments)
parse_options!(parser, arguments)
if arguments.size > 0
parser.options[:project_type] = arguments.shift.to_sym
end
parse_arguments!(parser, arguments)
set_default_arguments(parser)
parser.options
end
def parse_options!(parser, arguments)
parser.parse!
parser
end
def parse_arguments!(parser, arguments)
if arguments.size == 1
parser.options[:project_name] = arguments.shift
elsif arguments.size == 0
# default to the current directory.
else
raise Compass::Error, "Too many arguments were specified."
end
end
def set_default_arguments(parser)
parser.options[:framework] ||= :compass
parser.options[:pattern] ||= "project"
end
end
def is_project_creation?
true
end
end
end
end
================================================
FILE: cli/lib/compass/commands/default.rb
================================================
module Compass
module Commands
module DefaultOptionsParser
def set_options(opts)
opts.on("--trace") do
self.options[:trace] = true
end
opts.on("-?", "-h", "--help") do
self.options[:command] = Proc.new do
Help.new(working_path, options.merge(:help_command => "help"))
end
end
opts.on("-q", "--quiet") do
self.options[:quiet] = true
end
opts.on("-v", "--version") do
self.options[:command] = Proc.new do
PrintVersion.new(working_path, options)
end
end
super
end
end
class Default < Base
class << self
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(DefaultOptionsParser)
end
# def usage
# $stderr.puts caller.join("\n")
# "XXX"
# end
def parse!(arguments)
parser = option_parser(arguments)
parser.parse!
parser.options[:command] ||= Proc.new do
Help.new(working_path, options.merge(:help_command => "help"))
end
parser.options
end
end
def execute
instance_eval(&options[:command]).execute
end
end
end
end
================================================
FILE: cli/lib/compass/commands/extension_command.rb
================================================
require 'fileutils'
require 'compass/commands/base'
module Compass
module Commands
module ExtensionsOptionParser
def set_options(opts)
opts.banner = %Q{
Usage: compass extension install EXTENSION_NAME [options]
compass extension uninstall EXTENSION_NAME [options]
compass extension list
Description:
Manage the list of extensions on your system.
Compass to all of your compass projects.
Example:
compass extension install sassy-buttons
compass extension uninstall sassy-buttons
}
super
end
end
class ExtensionCommand < Base
register :extension
class << self
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(ExtensionsOptionParser)
end
def usage
option_parser([]).to_s
end
def description(command)
"Manage the list of compass extensions on your system"
end
def parse!(arguments)
{:arguments => arguments}
end
end
include InstallerCommand
def initialize(working_path, options)
super(working_path, options)
end
# all commands must implement perform
def perform
require 'rubygems/gem_runner'
Gem::GemRunner.new.run(options[:arguments])
end
end
end
end
================================================
FILE: cli/lib/compass/commands/help.rb
================================================
module Compass
module Commands
module HelpOptionsParser
def set_options(opts)
banner = %Q{Usage: compass help [command]
Description:
The Compass Stylesheet Authoring Framework helps you
build and maintain your stylesheets and makes it easy
for you to use stylesheet libraries provided by others.
Donating:
Compass is charityware. If you find it useful please make
a tax deductable donation: http://umdf.org/compass
To get help on a particular command please specify the command.
}
primary_commands = Compass::Commands.all.select do |c|
cmd = Compass::Commands[c]
cmd.respond_to?(:primary) && cmd.primary
end
other_commands = Compass::Commands.all - primary_commands
banner << command_list("Primary Commands:", primary_commands)
banner << command_list("Other Commands:", other_commands)
banner << "\nAvailable Frameworks & Patterns:\n\n"
banner << Compass::Frameworks.pretty_print
banner << "\nGlobal Options:\n"
opts.banner = banner
super
end
def command_list(header, commands)
list = "#{header}\n"
commands.sort_by{|c| c.to_s}.each do |command|
list << " * #{command}"
if Compass::Commands[command].respond_to? :description
list << "\t- #{Compass::Commands[command].description(command)}"
end
list << "\n"
end
list
end
end
class Help < Base
register :help
class << self
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(Compass::Exec::GlobalOptionsParser)
parser.extend(HelpOptionsParser)
end
def usage
option_parser([]).to_s
end
def description(command)
"Get help on a compass command or extension"
end
def parse!(arguments)
parser = option_parser(arguments)
parser.parse!
parser.options[:help_command] = arguments.shift || 'help'
parser.options
end
end
def execute
if Compass::Commands.command_exists? options[:help_command]
$command = options[:help_command]
puts Compass::Commands[options[:help_command]].usage
$command = "help"
elsif Compass::Frameworks.template_exists? options[:help_command]
puts Compass::Frameworks.template_usage(options[:help_command])
else
raise OptionParser::ParseError, "No such command: #{options[:help_command]}"
end
end
end
end
end
================================================
FILE: cli/lib/compass/commands/imports.rb
================================================
module Compass
module Commands
class Imports < ProjectBase
attr_accessor :options
register :imports
def initialize(working_path, options)
super
end
def execute
print ::Compass::Frameworks::ALL.map{|f|
"-I #{f.stylesheets_directory}"
}.join(' ')
end
class << self
def description(command)
"Emit an imports suitable for passing to the sass command-line."
end
def usage
"Usage: compass imports\n\n" +
"Prints out the imports known to compass.\n"+
"Useful for passing imports to the sass command line:\n" +
" sass -r compass `compass imports` a_file_using_compass.sass"
end
def parse!(arguments)
if arguments.join("").strip.size > 0
raise OptionParser::ParseError, "This command takes no options or arguments."
else
{}
end
end
end
end
end
end
================================================
FILE: cli/lib/compass/commands/installer_command.rb
================================================
require 'compass/installers'
module Compass
module Commands
module InstallerCommand
include Compass::Installers
def configure!
add_project_configuration
Compass.add_configuration(options, 'command_line')
Compass.discover_extensions!
Compass.add_configuration(installer.completed_configuration, 'installer')
end
def app
@app ||= Compass::AppIntegration.lookup(Compass.configuration.project_type)
end
def installer
@installer ||= if options[:bare]
Compass::Installers::BareInstaller.new(*installer_args)
else
app.installer(*installer_args)
end
end
def installer_args
[template_directory(options[:pattern] || "project"), project_directory, options]
end
end
end
end
================================================
FILE: cli/lib/compass/commands/interactive.rb
================================================
require 'compass/commands/project_base'
require 'compass/commands/update_project'
module Compass
module Commands
module InteractiveOptionsParser
def set_options(opts)
opts.banner = %Q{
Usage: compass interactive [path/to/project] [options]
Description:
Interactively evaluate SassScript
Options:
}.strip.split("\n").map{|l| l.gsub(/^ {0,10}/,'')}.join("\n")
super
end
end
class Interactive < ProjectBase
register :interactive
def initialize(working_path, options)
super
end
def perform
require 'sass/repl'
Sass::Repl.new.run
end
class << self
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(Compass::Exec::GlobalOptionsParser)
parser.extend(Compass::Exec::ProjectOptionsParser)
parser.extend(InteractiveOptionsParser)
end
def usage
option_parser([]).to_s
end
def description(command)
"Interactively evaluate SassScript"
end
def parse!(arguments)
parser = option_parser(arguments)
parser.parse!
parser.options
end
end
end
end
end
================================================
FILE: cli/lib/compass/commands/list_frameworks.rb
================================================
module Compass
module Commands
class ListFrameworks < ProjectBase
attr_accessor :options
register :frameworks
def initialize(working_path, options)
super
end
def execute
if options[:quiet]
Compass::Frameworks::ALL.each do |framework|
puts framework.name unless framework.name =~ /^_/
end
else
puts "Available Frameworks & Patterns:\n\n"
puts Compass::Frameworks.pretty_print
end
end
class << self
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(Compass::Exec::GlobalOptionsParser)
end
def usage
option_parser([]).to_s
end
def description(command)
"List the available frameworks"
end
def parse!(arguments)
parser = option_parser(arguments)
parser.parse!
parser.options
end
end
end
end
end
================================================
FILE: cli/lib/compass/commands/print_version.rb
================================================
module Compass
module Commands
module VersionOptionsParser
def set_options(opts)
opts.banner = %Q{Usage: compass version [options]
Options:
}
opts.on_tail("-?", "-h", "--help", "Print out this message.") do
puts opts
exit
end
opts.on("-q", "--quiet", "Just print the version string.") do
self.options[:quiet] = true
end
opts.on("--major", "Print the major version number") do
self.options[:major] = true
self.options[:custom] = true
end
opts.on("--minor", "Print up to the minor version number") do
self.options[:major] = true
self.options[:minor] = true
self.options[:custom] = true
end
opts.on("--patch", "Print up to the patch version number") do
self.options[:major] = true
self.options[:minor] = true
self.options[:patch] = true
self.options[:custom] = true
end
end
end
class PrintVersion < Base
register :version
class << self
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(VersionOptionsParser)
end
def usage
option_parser([]).to_s
end
def description(command)
"Print out version information"
end
def parse!(arguments)
parser = option_parser(arguments)
parser.parse!
parser.options
end
def long_output_string
lines = []
lines << "Compass #{::Compass.version[:string]}"
if name = ::Compass.version[:name]
lines.last << " (#{name})"
end
lines << "Copyright (c) 2008-#{Time.now.year} Chris Eppstein"
lines << "Released under the MIT License."
lines << "Compass is charityware."
lines << "Please make a tax deductable donation for a worthy cause: http://umdf.org/compass"
lines.join("\n")
end
end
attr_accessor :options
def initialize(working_path, options)
self.options = options
end
def execute
if options[:custom]
version = ""
version << "#{Compass.version[:major]}" if options[:major]
version << ".#{Compass.version[:minor]}" if options[:minor]
version << ".#{Compass.version[:patch]}" if options[:patch]
puts version
elsif options[:quiet]
puts ::Compass.version[:string]
else
puts self.class.long_output_string
end
end
end
end
end
================================================
FILE: cli/lib/compass/commands/project_base.rb
================================================
require 'fileutils'
require 'pathname'
require 'compass/commands/base'
require 'compass/commands/installer_command'
module Compass
module Commands
class ProjectBase < Base
attr_accessor :project_directory, :project_name, :options
def initialize(working_path, options = {})
super(working_path, options)
self.project_name = determine_project_name(working_path, options)
Compass.add_configuration({:project_path => determine_project_directory(working_path, options)}, "implied")
configure!
end
def execute
super
end
protected
def configure!
add_project_configuration
Compass.add_configuration(options, "command_line")
Compass.discover_extensions! unless skip_extension_discovery?
end
def add_project_configuration
defaults = Compass.configuration_for(options, "cli_defaults")
if options[:project_type]
project_type_config = Compass.configuration_for(options[:project_type])
project_type_config.inherit_from!(Compass.default_configuration)
defaults.inherit_from!(project_type_config)
end
Compass.add_project_configuration(options[:configuration_file], :defaults => defaults) do
options[:project_type]
end
end
def projectize(path)
Compass.projectize(path)
end
def project_directory
Compass.configuration.project_path
end
def project_css_subdirectory
Compass.configuration.css_dir
end
def project_src_subdirectory
Compass.configuration.sass_dir
end
def project_images_subdirectory
Compass.configuration.images_dir
end
def assert_project_directory_exists!
if File.exists?(project_directory) && !File.directory?(project_directory)
raise Compass::FilesystemConflict.new("#{project_directory} is not a directory.")
elsif !File.directory?(project_directory)
raise Compass::Error.new("#{project_directory} does not exist.")
end
end
private
def determine_project_name(working_path, options)
if options[:project_name]
File.basename(strip_trailing_separator(options[:project_name]))
else
File.basename(working_path)
end
end
def determine_project_directory(working_path, options)
if options[:project_name]
if absolute_path?(options[:project_name])
options[:project_name]
else
File.join(working_path, options[:project_name])
end
else
working_path
end
end
def absolute_path?(path)
# Pretty basic implementation
path.index(File::SEPARATOR) == 0 || path.index(':') == 1
end
def skip_extension_discovery?
false
end
end
end
end
================================================
FILE: cli/lib/compass/commands/project_stats.rb
================================================
require 'compass/commands/project_base'
require 'compass/commands/update_project'
module Compass
module Commands
module StatsOptionsParser
def set_options(opts)
opts.banner = %Q{
Usage: compass stats [path/to/project] [options]
Description:
Compile project at the path specified (or the current
directory if not specified) and then compute statistics
for the sass and css files in the project.
Options:
}.strip.split("\n").map{|l| l.gsub(/^ {0,10}/,'')}.join("\n")
super
end
end
class ProjectStats < UpdateProject
register :stats
def initialize(working_path, options)
super
assert_project_directory_exists!
end
def perform
super
require 'compass/stats'
compiler = new_compiler_instance
sass_files = sorted_sass_files(compiler)
total_label = "Total (#{sass_files.size} files):"
rows = [[ :-, :-, :-, :-, :-, :-, :-, :-, :- ],
[ 'Filename', 'Rules', 'Properties', 'Mixins Defs', 'Mixins Used', 'Filesize', 'CSS Selectors', 'CSS Properties', 'CSS Filesize' ],
[ :-, :-, :-, :-, :-, :-, :-, :-, :- ]]
maximums = [ total_label.length, 5, 10, 14, 11, 13, 13, 14, 14 ]
alignments = [ :left, :right, :right, :right, :right, :right, :right, :right, :right ]
delimiters = [ ['| ', ' |'], [' ', ' |'], [' ', ' |'], [' ', ' |'], [' ', ' |'], [' ', ' |'], [' ', ' |'], [' ', ' |'], [' ', ' |'] ]
formatters = [ nil, nil, nil, nil, nil, :kb, nil, nil, :kb ]
totals = [ total_label, 0, 0, 0, 0, 0, 0, 0, 0 ]
columns = rows.first.size
sass_files.each do |sass_file|
css_file = compiler.corresponding_css_file(sass_file) unless sass_file[0..0] == '_'
row = filename_columns(sass_file)
row += sass_columns(sass_file)
row += css_columns(css_file)
row.each_with_index do |c, i|
maximums[i] = [maximums[i].to_i, c.size].max
totals[i] = totals[i] + c.to_i if i > 0
end
rows << row
end
rows << [:-] * columns
rows << totals.map{|t| t.to_s}
rows << [:-] * columns
rows.each do |row|
row.each_with_index do |col, i|
print pad(col, maximums[i], :align => alignments[i], :left => delimiters[i].first, :right => delimiters[i].last, :formatter => formatters[i])
end
print "\n"
end
if @missing_css_parser
puts "\nInstall #{@missing_css_parser} to enable stats on your css files:\n\n\tgem install #{@missing_css_parser}"
end
end
def pad(c, max, options = {})
options[:align] ||= :left
if c == :-
filler = '-'
c = ''
else
filler = ' '
end
c = send(:"format_#{options[:formatter]}", c) if options[:formatter]
spaces = max - c.size
filled = filler * [spaces,0].max
"#{options[:left]}#{filled if options[:align] == :right}#{c}#{filled if options[:align] == :left}#{options[:right]}"
end
def format_kb(v)
return v unless v =~ /^\d+$/
v = Integer(v)
if v < 1024
"#{v} B"
else
v = v / 1024.0
"#{v.ceil} KB"
end
end
def sorted_sass_files(compiler)
sass_files = compiler.sass_files
sass_files.map! do |s|
filename = Compass.deprojectize(s, File.join(Compass.configuration.project_path, Compass.configuration.sass_dir))
[s, File.dirname(filename), File.basename(filename)]
end
sass_files = sass_files.sort_by do |s,d,f|
File.join(d, f[0] == ?_ ? f[1..-1] : f)
end
sass_files.map!{|s,d,f| s}
end
def filename_columns(sass_file)
filename = Compass.deprojectize(sass_file, working_path)
[filename]
end
def sass_columns(sass_file)
sf = Compass::Stats::SassFile.new(sass_file)
sf.analyze!
%w(rule_count prop_count mixin_def_count mixin_count file_size).map do |t|
sf.send(t).to_s
end
end
def css_columns(css_file)
if File.exists?(css_file)
cf = Compass::Stats::CssFile.new(css_file)
cf.analyze!
%w(selector_count prop_count file_size).map do |t|
cf.send(t).to_s
end
else
return [ '--', '--' , '--']
end
rescue LoadError => e
@missing_css_parser = e.message =~ /iconv/ ? "iconv" : "css_parser"
return [ 'DISABLED', 'DISABLED', 'DISABLED' ]
end
class << self
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(Compass::Exec::GlobalOptionsParser)
parser.extend(Compass::Exec::ProjectOptionsParser)
parser.extend(StatsOptionsParser)
end
def usage
option_parser([]).to_s
end
def description(command)
"Report statistics about your stylesheets"
end
def primary; false; end
def parse!(arguments)
parser = option_parser(arguments)
parser.parse!
parse_arguments!(parser, arguments)
parser.options
end
def parse_arguments!(parser, arguments)
if arguments.size == 1
parser.options[:project_name] = arguments.shift
elsif arguments.size == 0
# default to the current directory.
else
raise Compass::Error, "Too many arguments were specified."
end
end
end
end
end
end
================================================
FILE: cli/lib/compass/commands/project_structure.rb
================================================
require 'compass/commands/project_base'
require 'compass/commands/update_project'
module Compass
module Commands
module StructureOptionsParser
def set_options(opts)
opts.banner = %Q{
Usage: compass structure [path/to/project] [options]
Description:
Display the import structure of your stylesheets.
Options:
}.strip.split("\n").map{|l| l.gsub(/^ {0,10}/,'')}.join("\n")
super
end
end
class ProjectStats < UpdateProject
register :structure
def initialize(working_path, options)
super
assert_project_directory_exists!
end
def perform
@compiler = new_compiler_instance
(options[:sass_files] || sorted_sass_files).each do |sass_file|
print_tree(Compass.projectize(sass_file))
end
end
def print_tree(file, depth = 0, importer = @compiler.importer)
puts ((depth > 0 ? "| " : " ") * depth) + "+- " + Compass.deprojectize(file)
@compiler.staleness_checker.send(:compute_dependencies, file, importer).each do |(dep, dep_importer)|
print_tree(dep, depth + 1, dep_importer)# unless Compass.deprojectize(dep)[0...1] == "/"
end
end
def sorted_sass_files
sass_files = @compiler.sass_files
sass_files.map! do |s|
filename = Compass.deprojectize(s, File.join(Compass.configuration.project_path, Compass.configuration.sass_dir))
[s, File.dirname(filename), File.basename(filename)]
end
sass_files = sass_files.sort_by do |s,d,f|
File.join(d, f[0] == ?_ ? f[1..-1] : f)
end
sass_files.map!{|s,d,f| s}
end
class << self
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(Compass::Exec::GlobalOptionsParser)
parser.extend(Compass::Exec::ProjectOptionsParser)
parser.extend(StructureOptionsParser)
end
def usage
option_parser([]).to_s
end
def description(command)
"Report statistics about your stylesheets"
end
def primary; false; end
def parse!(arguments)
parser = option_parser(arguments)
parser.parse!
parse_arguments!(parser, arguments)
parser.options
end
def parse_arguments!(parser, arguments)
if arguments.size > 0
parser.options[:project_name] = arguments.shift if File.directory?(arguments.first)
parser.options[:sass_files] = arguments
end
end
end
end
end
end
================================================
FILE: cli/lib/compass/commands/registry.rb
================================================
module Compass::Commands
module Registry
def register(name, command_class)
@commands ||= Hash.new
@commands[name.to_sym] = command_class
end
def get(name)
return unless name
@commands ||= Hash.new
@commands[name.to_sym] || @commands[abbreviation_of(name)]
end
def abbreviation_of(name)
re = /^#{Regexp.escape(name)}/
matching = @commands.keys.select{|k| k.to_s =~ re}
if matching.size == 1
matching.first
elsif name =~ /^-/
nil
elsif matching.size > 1
raise Compass::Error, "Ambiguous abbreviation '#{name}'. Did you mean one of: #{matching.join(", ")}"
else
raise Compass::Error, "Command not found: #{name}"
end
end
def abbreviation?(name)
re = /^#{Regexp.escape(name)}/
@commands.keys.detect{|k| k.to_s =~ re}
end
def command_exists?(name)
@commands ||= Hash.new
name && (@commands.has_key?(name.to_sym) || abbreviation?(name))
end
def all
@commands.keys
end
alias_method :[], :get
alias_method :[]=, :register
end
extend Registry
end
================================================
FILE: cli/lib/compass/commands/sprite.rb
================================================
require 'compass/commands/project_base'
require 'compass/commands/update_project'
module Compass
module Commands
module SpriteOptionsParser
def set_options(opts)
opts.on("-f SPRITE_FILE") do |output_file|
self.options[:output_file] = output_file
end
opts.on("--skip-overrides", "Skip the generation of sprite overrides") do |skip_overrides|
self.options[:skip_overrides] = skip_overrides
end
opts.banner = %Q{
Usage: compass sprite [options] "images/path/to/sprites/*.png"
Description:
Generate a sprite import based on the given sprite directory.
Alternatively, you can simply do this in your sass files:
@import "sprite-folder/*.png"
And a magical, custom made sprite file will be imported.
Options:
}.strip.split("\n").map{|l| l.gsub(/^ {0,10}/,'')}.join("\n")
super
end
end
class Sprite < ProjectBase
register :sprite
def initialize(working_path, options)
super
assert_project_directory_exists!
end
def perform
relative_uri = options[:uri].gsub(/^#{Compass.configuration.images_dir}\//, '')
name = Compass::SpriteImporter.sprite_name(relative_uri)
sprites = Compass::SpriteImporter.new
options[:output_file] ||= File.join(Compass.configuration.sass_path, "sprites", "_#{name}.#{Compass.configuration.preferred_syntax}")
options[:skip_overrides] ||= false
contents = Compass::SpriteImporter.content_for_images(relative_uri, name, options[:skip_overrides])
if options[:output_file][-4..-1] != "scss"
contents = Sass::Engine.new(contents, Compass.sass_engine_options.merge(:syntax => :scss)).to_tree.to_sass
end
directory File.dirname(options[:output_file])
write_file options[:output_file], contents
end
class << self
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(Compass::Exec::GlobalOptionsParser)
parser.extend(Compass::Exec::ProjectOptionsParser)
parser.extend(SpriteOptionsParser)
end
def usage
option_parser([]).to_s
end
def description(command)
"Generate an import for your sprites."
end
def parse!(arguments)
parser = option_parser(arguments)
parser.parse!
parse_arguments!(parser, arguments)
parser.options
end
def parse_arguments!(parser, arguments)
parser.options[:uri] = arguments.shift
unless arguments.size == 0
raise Compass::Error, "Please specify at least one image to sprite."
end
end
end
end
end
end
================================================
FILE: cli/lib/compass/commands/stamp_pattern.rb
================================================
require 'fileutils'
require 'compass/commands/base'
require 'compass/commands/update_project'
module Compass
module Commands
module StampPatternOptionsParser
def set_options(opts)
opts.banner = %Q{Usage: compass install extension/pattern [path/to/project] [options]
Description:
Install an extension's pattern into your compass project
Example:
compass install blueprint/buttons
Options:
}
opts.on("-x", "--syntax SYNTAX", [:sass, :scss], "Specify the syntax to use when generating stylesheets.", "One of sass or scss. Defaults to scss.") do |syntax|
self.options[:preferred_syntax] = syntax
end
super
end
end
class StampPattern < ProjectBase
register :install
class << self
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(Compass::Exec::GlobalOptionsParser)
parser.extend(Compass::Exec::ProjectOptionsParser)
parser.extend(StampPatternOptionsParser)
end
def usage
option_parser([]).to_s
end
def description(command)
"Install an extension's pattern into your compass project"
end
def parse!(arguments)
parser = option_parser(arguments)
parser.parse!
parse_arguments!(parser, arguments)
parser.options
end
def parse_arguments!(parser, arguments)
if arguments.size == 0
raise OptionParser::ParseError, "Please specify a pattern."
end
pattern = arguments.shift.split('/', 2)
parser.options[:framework] = pattern[0]
parser.options[:pattern] = pattern[1]
if arguments.size > 0
parser.options[:project_name] = arguments.shift
end
if arguments.size > 0
raise OptionParser::ParseError, "Unexpected trailing arguments: #{arguments.join(" ")}"
end
end
end
include InstallerCommand
def initialize(working_path, options)
super(working_path, options)
end
# all commands must implement perform
def perform
installer.init
installer.run(:skip_finalization => true, :skip_preparation => !is_project_creation?)
UpdateProject.new(working_path, options).perform if installer.compilation_required?
installer.finalize(options.merge(:create => is_project_creation?))
end
def is_project_creation?
false
end
def template_directory(pattern)
File.join(framework.templates_directory, pattern)
end
end
end
end
================================================
FILE: cli/lib/compass/commands/unpack_extension.rb
================================================
require 'compass/commands/project_base'
require 'fileutils'
module Compass
module Commands
module ExtensionOptionsParser
def set_options(opts)
opts.banner = %Q{
Usage: compass unpack EXTENSION
Description:
Copy an extension into your extensions folder for easy access to the source code.
This makes it easier to peruse the source in unfamiliar projects. It is not recommended
that you change other extensions' source -- this makes it hard to take updates from
the original author. The following extensions are available:
FRAMEWORKS
Options:
}.strip.split("\n").map{|l| l.gsub(/^ {0,10}/,'')}.join("\n")
opts.banner.gsub!(/FRAMEWORKS/,Compass::Frameworks.pretty_print(true))
super
end
end
class UnpackExtension < ProjectBase
register :unpack
def initialize(working_path, options)
super
assert_project_directory_exists!
end
def perform
framework = Compass::Frameworks[options[:framework]]
unless framework
raise Compass::Error, "No extension named \"#{options[:framework]}\" was found."
end
files = Dir["#{framework.path}/**/*"]
extension_dir = File.join(Compass.configuration.extensions_path, framework.name)
FileUtils.rm_rf extension_dir
FileUtils.mkdir_p extension_dir
write_file File.join(extension_dir, "DO_NOT_MODIFY"), readme(framework)
files.each do |f|
next if File.directory?(f)
ending = f[(framework.path.size+1)..-1]
destination = File.join(extension_dir, ending)
FileUtils.mkdir_p(File.dirname(destination))
copy f, destination
end
puts "\nYou have unpacked \"#{framework.name}\""
puts
puts readme(framework)
end
def readme(framework)
%Q{| This is a copy of the "#{framework.name}" extension.
|
| It now overrides the original which was found here:
|
| #{framework.path}
|
| Unpacking an extension is useful when you need to easily peruse the
| extension's source. You might find yourself tempted to change the
| stylesheets here. If you do this, you'll find it harder to take
| updates from the original author. Sometimes this seems like a good
| idea at the time, but in a few months, you'll probably regret it.
|
| In the future, if you take an update of this framework, you'll need to run
|
| compass unpack #{framework.name}
|
| again or remove this unpacked extension.
|}.gsub(/^\s*\| ?/,"")
end
def skip_extension_discovery?
true
end
class << self
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(Compass::Exec::GlobalOptionsParser)
parser.extend(Compass::Exec::ProjectOptionsParser)
parser.extend(ExtensionOptionsParser)
end
def usage
option_parser([]).to_s
end
def description(command)
"Copy an extension into your extensions folder."
end
def parse!(arguments)
parser = option_parser(arguments)
parser.parse!
parse_arguments!(parser, arguments)
parser.options
end
def parse_arguments!(parser, arguments)
if arguments.size == 1
parser.options[:framework] = arguments.shift
elsif arguments.size == 0
raise Compass::Error, "Please specify an extension to unpack."
else
raise Compass::Error, "Too many arguments were specified."
end
end
end
end
end
end
================================================
FILE: cli/lib/compass/commands/update_project.rb
================================================
require 'compass/commands/project_base'
require 'compass/compiler'
module Compass
module Commands
module CompileProjectOptionsParser
def set_options(opts)
opts.banner = %Q{
Usage: compass compile [path/to/project] [path/to/project/src/file.sass ...] [options]
Description:
compile project at the path specified or the current directory if not specified.
Options:
}.split("\n").map{|l| l.gsub(/^ */,'')}.join("\n")
opts.on("--[no-]sourcemap", "Generate a sourcemap during compilation.") do |sm|
self.options[:sourcemap] = sm
end
opts.on("--time", "Display compilation times.") do
self.options[:time] = true
end
opts.on("--debug-info", "Turns on sass's debuging information") do
self.options[:debug_info]= true
end
opts.on("--no-debug-info", "Turns off sass's debuging information") do
self.options[:debug_info]= false
end
super
end
end
class UpdateProject < ProjectBase
register :compile
def initialize(working_path, options)
super
assert_project_directory_exists!
end
def perform
compiler = new_compiler_instance
check_for_sass_files!(compiler)
prepare_project!(compiler)
compiler.compile!
if compiler.error_count > 0
compiler.logger.red do
compiler.logger.log "Compilation failed in #{compiler.error_count} files."
end
failed!
end
end
def prepare_project!(compiler)
if options[:project_name]
Compass.configuration.project_path = File.expand_path(options[:project_name])
end
if config_file = new_config?(compiler)
compiler.logger.record :modified, relativize(config_file)
compiler.logger.record :clean, relativize(Compass.configuration.css_path)
compiler.clean!
end
end
# Determines if the configuration file is newer than any css file
def new_config?(compiler)
config_file = Compass.detect_configuration_file
return false unless config_file
config_mtime = File.mtime(config_file)
compiler.file_list.each do |(_, css_filename, _)|
return config_file if File.exists?(css_filename) && config_mtime > File.mtime(css_filename)
end
nil
end
def check_for_sass_files!(compiler)
file_list = compiler.file_list
if file_list.empty?
message = "Compass can't find any Sass files to compile.\nIs your compass configuration correct?.\nIf you're trying to start a new project, you have left off the directory argument.\n"
message << "Run \"compass -h\" to get help."
raise Compass::Error, message
elsif missing = file_list.find {|(sass_file, _, _)| !File.exist?(sass_file)}
raise Compass::Error, "File not found: #{missing[0]}"
end
end
def new_compiler_instance
Compass::SassCompiler.new(compiler_options)
end
def compiler_options
transfer_options(options, {}, :time, :debug_info, :only_sass_files, :force, :quiet)
end
def transfer_options(from, to, *keys)
keys.each do |k|
to[k] = from[k] unless from[k].nil?
end
to
end
class << self
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(Compass::Exec::GlobalOptionsParser)
parser.extend(Compass::Exec::ProjectOptionsParser)
parser.extend(CompileProjectOptionsParser)
end
def usage
option_parser([]).to_s
end
def primary; true; end
def description(command)
"Compile Sass stylesheets to CSS"
end
def parse!(arguments)
parser = option_parser(arguments)
parser.parse!
parse_arguments!(parser, arguments)
parser.options
end
def parse_arguments!(parser, arguments)
if arguments.size > 0
parser.options[:project_name] = arguments.shift if File.directory?(arguments.first)
unless arguments.empty?
parser.options[:only_sass_files] = absolutize(*arguments)
end
end
end
def absolutize(*paths)
paths.map {|path| File.expand_path(path) }
end
end
end
end
end
================================================
FILE: cli/lib/compass/commands/validate_project.rb
================================================
require 'compass/commands/project_base'
require 'compass/commands/update_project'
module Compass
module Commands
module ValidationOptionsParser
def set_options(opts)
opts.banner = %Q{
Usage: compass validate [path/to/project] [options]
Description:
Compile project at the path specified or the current
directory if not specified and then validate the
generated CSS.
Options:
}.strip.split("\n").map{|l| l.gsub(/^ {0,10}/,'')}.join("\n")
super
end
end
class ValidateProject < ProjectBase
register :validate
def initialize(working_path, options)
super
assert_project_directory_exists!
end
def perform
require 'compass/validator'
UpdateProject.new(working_path, options).perform
Dir.chdir Compass.configuration.project_path do
Validator.new(project_css_subdirectory).validate()
end
end
class << self
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(Compass::Exec::GlobalOptionsParser)
parser.extend(Compass::Exec::ProjectOptionsParser)
parser.extend(ValidationOptionsParser)
end
def usage
option_parser([]).to_s
end
def description(command)
"Validate your generated css."
end
def parse!(arguments)
parser = option_parser(arguments)
parser.parse!
parse_arguments!(parser, arguments)
parser.options
end
def parse_arguments!(parser, arguments)
if arguments.size == 1
parser.options[:project_name] = arguments.shift
elsif arguments.size == 0
# default to the current directory.
else
raise Compass::Error, "Too many arguments were specified."
end
end
end
end
end
end
================================================
FILE: cli/lib/compass/commands/watch_project.rb
================================================
# encoding: UTF-8
require 'fileutils'
require 'pathname'
require 'compass/commands/update_project'
require "compass/sass_compiler"
module Compass
module Commands
module WatchProjectOptionsParser
def set_options(opts)
super
opts.banner = %Q{
Usage: compass watch [path/to/project] [path/to/project/src/file.sass ...] [options]
Description:
watch the project for changes and recompile when they occur.
Options:
}.split("\n").map{|l| l.gsub(/^ */,'')}.join("\n")
opts.on("--poll", :NONE, "Check periodically if there's been changes.") do
self.options[:poll] = 1 # check every 1 second.
end
end
end
class WatchProject < UpdateProject
register :watch
attr_accessor :last_update_time, :last_sass_files
def perform
compiler = new_compiler_instance
compiler.logger.time = true if options[:time]
prepare_project!(compiler)
compiler.logger.log ">>> #{compiler.logger.color(:green)}Compass is watching for changes.#{compiler.logger.color(:clear)} #{compiler.logger.color(:red)}Press Ctrl-C to Stop.#{compiler.logger.color(:clear)}"
begin
compiler.watch!(:additional_watch_paths => additional_watch_paths, &method(:notify_watches))
happy_styling!(compiler.logger)
rescue Interrupt
happy_styling!(compiler.logger)
end
end
def happy_styling!(logger)
logger.log "\n#{logger.color(:yellow)}★★★ #{logger.color(:blue)}Happy Styling!#{logger.color(:yellow)} ★★★#{logger.color(:clear)}"
end
def compiler_options
super.merge(:poll => options[:poll], :full_exception => true)
end
def additional_watch_paths
Compass.configuration.watches.map do |watch|
pathname = Pathname.new(File.join(Compass.configuration.project_path, watch.glob))
real_path = nil
pathname.ascend do |p|
if p.exist?
real_path = p
break
end
end
real_path
end.compact.uniq
end
def notify_watches(modified, added, removed)
project_path = Compass.configuration.project_path
files = {:modified => modified,
:added => added,
:removed => removed}
run_once, run_each = Compass.configuration.watches.partition {|w| w.run_once_per_changeset?}
run_once.each do |watcher|
if file = files.values.flatten.detect{|f| watcher.match?(f) }
action = files.keys.detect{|k| files[k].include?(file) }
watcher.run_callback(project_path, relative_to(file, project_path), action)
end
end
run_each.each do |watcher|
files.each do |action, list|
list.each do |file|
if watcher.match?(file)
watcher.run_callback(project_path, relative_to(file, project_path), action)
end
end
end
end
end
def relative_to(f, dir)
Pathname.new(f).relative_path_from(Pathname.new(dir))
rescue ArgumentError # does not share a common path.
f
end
class << self
def description(command)
"Compile Sass stylesheets to CSS when they change"
end
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(Compass::Exec::GlobalOptionsParser)
parser.extend(Compass::Exec::ProjectOptionsParser)
parser.extend(CompileProjectOptionsParser)
parser.extend(WatchProjectOptionsParser)
end
end
end
end
end
================================================
FILE: cli/lib/compass/commands/write_configuration.rb
================================================
require 'compass/commands/project_base'
module Compass
module Commands
module ConfigurationOptionsParser
def set_options(opts)
opts.banner = %Q{
Usage: compass config [path/to/config_file.rb] [options]
Description:
Generate a configuration file for the options specified.
Compass will recognize configuration files in the
following locations relative to the project root:
* #{Compass::Configuration::Helpers::KNOWN_CONFIG_LOCATIONS.join("
* ")}
Any other location, and you'll need to specify it when working with the command line tool using the -c option.
Options:
}.strip.split("\n").map{|l| l.gsub(/^ {0,10}/,'')}.join("\n")
opts.on("--debug [PROPERTY]", "Debug your configuration by printing out details.") do |prop|
self.options[:debug] = prop.nil? ? true : prop.to_sym
end
opts.on("-p PROPERTY", "--property PROPERTY", "Print out the value of a particular configuration property") do |prop|
self.options[:display] = prop.to_sym
end
super
end
end
class WriteConfiguration < ProjectBase
register :config
include InstallerCommand
def initialize(working_path, options)
super
assert_project_directory_exists!
end
def add_project_configuration
Compass.add_project_configuration
end
def perform
if options[:display]
if Compass.configuration.respond_to?(options[:display])
puts Compass.configuration.send(options[:display])
else
raise Compass::Error, "ERROR: configuration property '#{options[:display]}' does not exist"
end
elsif options[:debug]
puts "Configuration sources:"
c = Compass.configuration
while c
print c.name
c = c.inherited_data
print ", " if c
end
print "\n"
Compass.configuration.debug.each do |prop, values|
if options[:debug].is_a?(Symbol)
next unless prop == options[:debug]
end
puts "***** #{prop} = #{values.first[:resolved].inspect} *****"
[:default, :value, :raw, :resolved].each do |kind|
puts "#{kind}: " + values.inject([]){|m, v| m << v[kind]}.map{|v| v.nil? ? '-' : v.inspect}.join(", ")
end
end
else
config_file = options[:configuration_file]
config_file ||= Compass.detect_configuration_file
config_file ||= Compass::Configuration::Helpers::KNOWN_CONFIG_LOCATIONS.first
directory File.dirname(config_file)
installer.write_configuration_files(config_file)
end
end
def installer_args
[nil, project_directory, options]
end
def explicit_config_file_must_be_readable?
false
end
class << self
def option_parser(arguments)
parser = Compass::Exec::CommandOptionParser.new(arguments)
parser.extend(Compass::Exec::GlobalOptionsParser)
parser.extend(Compass::Exec::ProjectOptionsParser)
parser.extend(ConfigurationOptionsParser)
end
def usage
option_parser([]).to_s
end
def description(command)
"Generate a configuration file for the provided command line options."
end
def parse!(arguments)
parser = option_parser(arguments)
parser.parse!
parse_arguments!(parser, arguments)
parser.options
end
def parse_arguments!(parser, arguments)
if arguments.size == 1
parser.options[:configuration_file] = arguments.shift
elsif arguments.size == 0
# default to the current directory.
else
raise Compass::Error, "Too many arguments were specified."
end
end
end
end
end
end
================================================
FILE: cli/lib/compass/commands.rb
================================================
module Compass::Commands
end
require 'compass/commands/registry'
%w(base project_base default help list_frameworks
update_project watch_project create_project clean_project extension_command
imports installer_command print_version project_stats stamp_pattern
sprite validate_project write_configuration interactive unpack_extension
).each do |lib|
require "compass/commands/#{lib}"
end
Compass.discover_extensions!
================================================
FILE: cli/lib/compass/compiler.rb
================================================
require 'pathname'
module Compass
class Compiler
include Actions
attr_accessor :working_path, :from, :to, :options, :sass_options, :staleness_checker, :importer
def initialize(working_path, from, to, options)
Compass::Deprecation.deprecated!(:compass_compiler_constructor,
"Compass::Compiler is deprecated. Use Compass::SassCompiler instead.")
self.working_path = working_path.to_s
self.from, self.to = File.expand_path(from), to
self.logger = options.delete(:logger)
sass_opts = options.delete(:sass) || {}
self.options = options
self.sass_options = options.dup
self.sass_options.delete(:quiet)
self.sass_options.update(sass_opts)
self.sass_options[:cache_location] ||= determine_cache_location
self.sass_options[:filesystem_importer] ||= Sass::Importers::Filesystem
self.sass_options[:importer] = self.importer = self.sass_options[:filesystem_importer].new(from)
self.sass_options[:compass] ||= {}
self.sass_options[:compass][:logger] = self.logger
self.sass_options[:compass][:environment] = Compass.configuration.environment
self.sass_options[:compass][:compiler_in_use] = true
reset_staleness_checker!
end
def reset_staleness_checker!
self.staleness_checker = nil
#Sass::Plugin::StalenessChecker.dependencies_cache = {}
self.staleness_checker = Sass::Plugin::StalenessChecker.new(sass_options)
end
def determine_cache_location
Compass.configuration.cache_path || Sass::Plugin.options[:cache_location] || File.join(working_path, ".sass-cache")
end
def sass_files(options = {})
exclude_partials = options.fetch(:exclude_partials, true)
@sass_files = self.options[:sass_files] || Dir.glob(separate("#{from}/**/#{'[^_]' if exclude_partials}*.s[ac]ss"))
end
def relative_stylesheet_name(sass_file)
sass_file[(from.length + 1)..-1]
end
def stylesheet_name(sass_file)
if sass_file.index(from) == 0
sass_file[(from.length + 1)..-6].sub(/\.css$/,'')
else
raise Compass::Error, "You must compile individual stylesheets from the project directory."
end
end
def css_files
@css_files ||= sass_files.map{|sass_file| corresponding_css_file(sass_file)}
end
def sourcemap_files
@sourcemap_files ||= sass_files.map{|sass_file| corresponding_sourcemap_file(sass_file)}
end
def corresponding_css_file(sass_file)
"#{to}/#{stylesheet_name(sass_file)}.css"
end
def corresponding_sourcemap_file(sass_file)
"#{to}/#{stylesheet_name(sass_file)}.css.map"
end
def target_directories
css_files.map{|css_file| File.dirname(css_file)}.uniq.sort.sort_by{|d| d.length }
end
# Returns the sass file that needs to be compiled, if any.
def out_of_date?
sass_files.zip(css_files).each do |sass_filename, css_filename|
return sass_filename if needs_update?(css_filename, sass_filename)
end
false
end
def needs_update?(css_filename, sass_filename)
staleness_checker.stylesheet_needs_update?(css_filename, File.expand_path(sass_filename), importer)
end
# Determines if the configuration file is newer than any css file
def new_config?
config_file = Compass.detect_configuration_file
return false unless config_file
config_mtime = File.mtime(config_file)
css_files.each do |css_filename|
return config_file if File.exists?(css_filename) && config_mtime > File.mtime(css_filename)
end
nil
end
def reset!
reset_staleness_checker!
@sass_files = nil
@css_files = nil
@sourcemap_files = nil
end
def clean!
remove options[:cache_location]
css_files.zip(sourcemap_files).each do |css_file, sourcemap_file|
remove css_file
remove sourcemap_file
end
end
def run
failure_count = 0
if new_config?
# Wipe out the cache and force compilation if the configuration has changed.
remove options[:cache_location] if options[:cache_location]
options[:force] = true
end
# Make sure the target directories exist
target_directories.each {|dir| directory dir}
# Compile each sass file.
result = timed do
sass_files.zip(css_files, sourcemap_files).each do |sass_filename, css_filename, sourcemap_filename|
begin
compile_if_required sass_filename, css_filename, sourcemap_filename
rescue Sass::SyntaxError => e
failure_count += 1
handle_exception(sass_filename, css_filename, e)
end
end
end
if options[:time]
puts "Compilation took #{(result.__duration * 1000).round / 1000.0}s"
end
return failure_count
end
def compile_if_required(sass_filename, css_filename, sourcemap_filename = nil)
if should_compile?(sass_filename, css_filename, sourcemap_filename)
compile sass_filename, css_filename, sourcemap_filename
else
logger.record :unchanged, basename(sass_filename) unless options[:quiet]
remove(sourcemap_filename) if sourcemap_filename && !options[:sourcemap]
end
end
def timed(timed_thing = lambda {|res| res})
start_time = Time.now
res = yield
end_time = Time.now
has_duration = timed_thing.call(res)
has_duration.instance_variable_set("@__duration", end_time - start_time)
def has_duration.__duration
@__duration
end
res
end
# Compile one Sass file
def compile(sass_filename, css_filename, sourcemap_filename = nil)
css_content, sourcemap = logger.red do
timed(lambda {|r| r[0]}) do
engine = engine(sass_filename, css_filename, sourcemap_filename)
if sourcemap_filename && options[:sourcemap]
engine.render_with_sourcemap(relative_path(css_filename, sourcemap_filename))
else
[engine.render, nil]
end
end
end
duration = options[:time] ? "(#{(css_content.__duration * 1000).round / 1000.0}s)" : ""
write_file(css_filename, css_content, options.merge(:force => true, :extra => duration), sass_options[:unix_newlines])
Compass.configuration.run_stylesheet_saved(css_filename)
if sourcemap && sourcemap_filename
sourcemap_content = sourcemap.to_json(:css_path => css_filename,
:sourcemap_path => sourcemap_filename)
write_file(sourcemap_filename, sourcemap_content, options.merge(:force => true), sass_options[:unix_newlines])
Compass.configuration.run_sourcemap_saved(sourcemap_filename)
elsif sourcemap_filename && File.exist?(sourcemap_filename)
remove sourcemap_filename
Compass.configuration.run_sourcemap_removed(sourcemap_filename)
end
end
def relative_path(from_path, to_path)
Pathname.new(to_path).relative_path_from(Pathname.new(from_path).dirname).to_s
end
def should_compile?(sass_filename, css_filename, sourcemap_filename = nil)
return true if css_filename && !File.exist?(css_filename)
return true if sourcemap_filename && options[:sourcemap] && !File.exist?(sourcemap_filename)
options[:force] ||
needs_update?(css_filename, sass_filename) ||
(options[:sourcemap] && needs_update?(sourcemap_filename, sass_filename))
end
# A sass engine for compiling a single file.
def engine(sass_filename, css_filename, sourcemap_filename = nil)
syntax = (sass_filename =~ /\.(s[ac]ss)$/) && $1.to_sym || :sass
opts = sass_options.merge(:filename => sass_filename,
:css_filename => css_filename,
:syntax => syntax,
:sourcemap_filename => sourcemap_filename)
Sass::Engine.new(open(sass_filename).read, opts)
end
# Place the syntax error into the target css file,
# formatted to display in the browser (in development mode)
# if there's an error.
def handle_exception(sass_filename, css_filename, e)
exception_file = basename(e.sass_filename || sass_filename)
file = basename(sass_filename)
exception_file = nil if exception_file == file
formatted_error = "(Line #{e.sass_line}#{ " of #{exception_file}" if exception_file}: #{e.message})"
logger.record :error, file, formatted_error
Compass.configuration.run_stylesheet_error(sass_filename, formatted_error)
write_file css_filename, error_contents(e, sass_filename), options.merge(:force => true), sass_options[:unix_newlines]
end
# Haml refactored this logic in 2.3, this is backwards compatibility for either one
def error_contents(e, sass_filename)
if show_full_exception?
e.sass_template = sass_filename
Sass::SyntaxError.exception_to_css(e)
else
header = Sass::SyntaxError.send(:header_string, e, 1)
< e
raise e if e.is_a? SystemExit
if e.is_a?(::Compass::Error) || e.is_a?(OptionParser::ParseError)
$stderr.puts e.message
else
::Compass::Exec::Helpers.report_error(e, @options || {})
end
return 1
end
end
protected
def perform!
$command = args.shift
command_class = Compass::Commands[$command]
unless command_class
args.unshift($command)
$command = "help"
command_class = Compass::Commands::Default
end
@options = if command_class.respond_to?("parse_#{$command}!")
command_class.send("parse_#{$command}!", args)
else
command_class.parse!(args)
end
cmd = command_class.new(Dir.getwd, @options)
cmd.execute
cmd.successful? ? 0 : 1
rescue OptionParser::ParseError => e
puts "Error: #{e.message}"
puts command_class.usage if command_class.respond_to?(:usage)
end
end
end
================================================
FILE: cli/lib/compass/exec.rb
================================================
require 'compass/dependencies'
require 'optparse'
require 'compass/logger'
require 'compass/errors'
require 'compass/actions'
require 'compass/installers'
require 'compass/commands'
require 'rbconfig'
require 'pathname'
begin
require 'win32console' if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
rescue LoadError
$boring = true
end
module Compass::Exec
end
%w(helpers sub_command_ui
global_options_parser project_options_parser
command_option_parser).each do |lib|
require "compass/exec/#{lib}"
end
================================================
FILE: cli/lib/compass/generated_version.rb
================================================
module Compass
# This file intentionall does nothing.
# The compass build scripts put the release VERSION constant here.
end
================================================
FILE: cli/lib/compass/installers/bare_installer.rb
================================================
module Compass
module Installers
class BareInstaller < Base
def completed_configuration
nil
end
def init
directory targetize("")
directory targetize(Compass.configuration.sass_dir)
end
def prepare
end
def install
config_file ||= targetize('config.rb')
write_file config_file, config_contents
end
def config_contents
project_path, Compass.configuration.project_path = Compass.configuration.project_path, nil
Compass.configuration.serialize
ensure
Compass.configuration.project_path = project_path
end
def finalize(options = {})
puts <<-NEXTSTEPS
*********************************************************************
Congratulations! Your compass project has been created.
You may now add sass stylesheets to the #{Compass.configuration.sass_dir} subdirectory of your project.
Sass files beginning with an underscore are called partials and won't be
compiled to CSS, but they can be imported into other sass stylesheets.
You can configure your project by editing the config.rb configuration file.
You must compile your sass stylesheets into CSS when they change.
This can be done in one of the following ways:
1. To compile on demand:
compass compile [path/to/project]
2. To monitor your project for changes and automatically recompile:
compass watch [path/to/project]
More Resources:
* Website: http://compass-style.org/
* Sass: http://sass-lang.com
* Community: http://groups.google.com/group/compass-users/
NEXTSTEPS
end
end
end
end
================================================
FILE: cli/lib/compass/installers/base.rb
================================================
module Compass
module Installers
class Base
include Actions
attr_accessor :template_path, :target_path, :working_path
attr_accessor :options
def initialize(template_path, target_path, options = {})
@template_path = template_path
@target_path = target_path
@working_path = Dir.getwd
@options = options
self.logger = options[:logger]
end
[:css_dir, :sass_dir, :images_dir, :javascripts_dir, :http_stylesheets_path, :fonts_dir, :preferred_syntax].each do |dir|
define_method dir do
Compass.configuration.send(dir)
end
define_method "#{dir}_without_default" do
Compass.configuration.send("#{dir}_without_default")
end
end
# Runs the installer.
# Every installer must conform to the installation strategy of prepare, install, and then finalize.
# A default implementation is provided for each step.
def run(run_options = {})
prepare unless run_options[:skip_preparation]
install unless options[:prepare]
finalize(options.merge(run_options)) unless options[:prepare] || run_options[:skip_finalization]
end
# The default prepare method -- it is a no-op.
# Generally you would create required directories, etc.
def prepare
end
# The install method override this to install
def install
raise "Not Yet Implemented"
end
# The default finalize method -- it is a no-op.
# This could print out a message or something.
def finalize(options = {})
end
def compilation_required?
false
end
def pattern_name_as_dir
"#{options[:pattern_name]}/" if options[:pattern_name]
end
def self.installer(type, installer_opts = {}, &locator)
locator ||= lambda{|to| to}
loc_method = "install_location_for_#{type}".to_sym
define_method("simple_#{loc_method}", locator)
define_method(loc_method) do |to, options|
if options[:like] && options[:like] != type
send("install_location_for_#{options[:like]}", to, options)
else
send("simple_#{loc_method}", to)
end
end
define_method "install_#{type}" do |from, to, options|
from = templatize(from)
to = targetize(send(loc_method, to, options))
is_binary = installer_opts[:binary] || options[:binary]
if is_binary
copy from, to, nil, is_binary
else
contents = File.new(from).read
if options.delete(:erb)
ctx = TemplateContext.ctx(:to => to, :options => options)
contents = process_erb(contents, ctx)
end
write_file to, contents
end
end
end
installer :stylesheet do |to|
"#{sass_dir}/#{pattern_name_as_dir}#{to}"
end
def install_stylesheet(from, to, options)
from = templatize(from)
to = targetize(install_location_for_stylesheet(to, options))
contents = File.new(from).read
if options.delete(:erb)
ctx = TemplateContext.ctx(:to => to, :options => options)
contents = process_erb(contents, ctx)
end
if preferred_syntax.to_s != from[-4..-1]
# logger.record :convert, basename(from)
tree = Sass::Engine.new(contents, Compass.sass_engine_options.merge(:syntax => from[-4..-1].intern)).to_tree
contents = tree.send("to_#{preferred_syntax}")
to[-4..-1] = preferred_syntax.to_s
end
write_file to, contents
end
installer :css do |to|
"#{css_dir}/#{to}"
end
installer :image, :binary => true do |to|
"#{images_dir}/#{to}"
end
installer :javascript do |to|
"#{javascripts_dir}/#{to}"
end
installer :font do |to|
"#{fonts_dir}/#{to}"
end
installer :file do |to|
"#{pattern_name_as_dir}#{to}"
end
installer :html do |to|
"#{pattern_name_as_dir}#{to}"
end
def install_directory(from, to, options)
d = if within = options[:within]
if respond_to?(within)
targetize("#{send(within)}/#{to}")
else
raise Compass::Error, "Unrecognized location: #{within}"
end
else
targetize(to)
end
directory d
end
alias install_html_without_haml install_html
def install_html(from, to, options)
if to =~ /\.haml$/
require 'haml'
to = to[0..-(".haml".length+1)]
if respond_to?(:install_location_for_html)
to = install_location_for_html(to, options)
end
contents = File.read(templatize(from))
if options.delete(:erb)
ctx = TemplateContext.ctx(:to => to, :options => options)
contents = process_erb(contents, ctx)
end
Compass.configure_sass_plugin!
html = Haml::Engine.new(contents, :filename => templatize(from)).render
write_file(targetize(to), html, options)
else
install_html_without_haml(from, to, options)
end
end
# returns an absolute path given a path relative to the current installation target.
# Paths can use unix style "/" and will be corrected for the current platform.
def targetize(path)
strip_trailing_separator File.join(target_path, separate(path))
end
# returns an absolute path given a path relative to the current template.
# Paths can use unix style "/" and will be corrected for the current platform.
def templatize(path)
strip_trailing_separator File.join(template_path, separate(path))
end
# Emits an HTML fragment that can be used to link to the compiled css files
def stylesheet_links
""
end
end
end
end
require 'compass/installers/bare_installer'
require 'compass/installers/manifest_installer'
================================================
FILE: cli/lib/compass/installers/manifest.rb
================================================
module Compass
module Installers
class Manifest
include Enumerable
# A Manifest entry
class Entry < Struct.new(:type, :from, :options)
def to
options[:to] || from
end
end
attr_reader :options
def initialize(manifest_file = nil, options = {})
@entries = []
@options = options
@generate_config = true
@compile_after_generation = true
parse(manifest_file) if manifest_file
end
def self.known_extensions
@known_extensions ||= {}
end
def self.plural_types
@plural_types ||= {}
end
def self.type(t, options = {})
Array(options[:extensions]).each do |ext|
self.known_extensions[ext] = t
end
self.plural_types[options[:plural]] = t if options[:plural]
eval <<-END
def #{t}(from, options = {})
@entries << Entry.new(:#{t}, from, options)
end
def has_#{t}?
@entries.detect {|e| e.type == :#{t}}
end
def each_#{t}
@entries.select {|e| e.type == :#{t}}.each {|e| yield e}
end
END
end
type :stylesheet, :plural => :stylesheets, :extensions => %w(scss sass)
type :image, :plural => :images, :extensions => %w(png gif jpg jpeg tiff gif)
type :javascript, :plural => :javascripts, :extensions => %w(js)
type :font, :plural => :fonts, :extensions => %w(eot otf woff ttf)
type :html, :plural => :html, :extensions => %w(html haml)
type :file, :plural => :files
type :directory, :plural => :directories
def discover(type)
type = self.class.plural_types[type] || type
dir = File.dirname(@manifest_file)
Dir.glob("#{dir}/**/*").each do |file|
next if /manifest\.rb/ =~ file
short_name = file[(dir.length+1)..-1]
options = {}
ext = if File.extname(short_name) == ".erb"
options[:erb] = true
File.extname(short_name[0..-5])
else
File.extname(short_name)
end[1..-1]
file_type = self.class.known_extensions[ext]
file_type = :file if file_type.nil?
file_type = :directory if File.directory?(file)
if type == :all || type == file_type
send(file_type, short_name, options)
end
end
end
def help(value = nil)
if value
@help = value
else
@help
end
end
attr_reader :welcome_message_options
def welcome_message(value = nil, options = {})
if value
@welcome_message = value
@welcome_message_options = options
else
@welcome_message
end
end
def welcome_message_options
@welcome_message_options || {}
end
def description(value = nil)
if value
@description = value
else
@description
end
end
# Enumerates over the manifest files
def each
@entries.each {|e| yield e}
end
def generate_config?
@generate_config
end
def compile?
@compile_after_generation
end
protected
def no_configuration_file!
@generate_config = false
end
def skip_compilation!
@compile_after_generation = false
end
def with_manifest(manifest_file)
@manifest_file = manifest_file
yield
ensure
@manifest_file = nil
end
# parses a manifest file which is a ruby script
# evaluated in a Manifest instance context
def parse(manifest_file)
with_manifest(manifest_file) do
if File.exists?(manifest_file)
open(manifest_file) do |f|
eval(f.read, instance_binding, manifest_file)
end
else
eval("discover :all", instance_binding, manifest_file)
end
end
end
def instance_binding
binding
end
end
end
end
================================================
FILE: cli/lib/compass/installers/manifest_installer.rb
================================================
module Compass
module Installers
class ManifestInstaller < Base
attr_accessor :manifest
def initialize(template_path, target_path, options = {})
super
@manifest = Manifest.new(manifest_file, options) if template_path
end
def manifest_file
@manifest_file ||= File.join(template_path, "manifest.rb")
end
# Initializes the project to work with compass
def init
dirs = manifest.map do |entry|
unless entry.type == :directory
loc = send("install_location_for_#{entry.type}", entry.to, entry.options)
File.dirname(loc)
end
end.compact
if manifest.has_stylesheet?
dirs << sass_dir
dirs << css_dir
end
dirs.uniq.sort.each do |dir|
directory targetize(dir)
end
end
# The default install method. Calls install_ methods in the order specified by the manifest.
def install
manifest.each do |entry|
send("install_#{entry.type}", entry.from, entry.to, entry.options)
end
end
def stylesheet_links
html = "\n"
manifest.each_stylesheet do |stylesheet|
# Skip partials.
next if File.basename(stylesheet.from)[0..0] == "_"
media = if stylesheet.options[:media]
%Q{ media="#{stylesheet.options[:media]}"}
end
ss_line = %Q{ }
if stylesheet.options[:condition]
ss_line = " "
end
html << ss_line + "\n"
end
html << ""
end
end
end
end
================================================
FILE: cli/lib/compass/installers/template_context.rb
================================================
module Compass
module Installers
class TemplateContext
def self.ctx(*arguments)
new(*arguments).send(:get_binding)
end
def initialize(template, locals = {})
@template = template
@locals = locals
end
def http_stylesheets_path
config.http_stylesheets_path ||
config.default_for(:http_stylesheets_path) ||
config.http_root_relative(config.css_dir)
end
Compass::Configuration::ATTRIBUTES.each do |attribute|
unless instance_methods.include?(attribute.to_s)
define_method attribute do
config.send(attribute) || config.default_for(attribute)
end
end
end
def config
Compass.configuration
end
alias configuration config
protected
def get_binding
@locals.each do |k, v|
eval("#{k} = v")
end
binding
end
end
end
end
================================================
FILE: cli/lib/compass/installers.rb
================================================
%w(manifest template_context base manifest_installer bare_installer).each do |f|
require "compass/installers/#{f}"
end
================================================
FILE: cli/lib/compass/logger.rb
================================================
module Compass
class Logger
COLORS = { :clear => 0, :red => 31, :green => 32, :yellow => 33, :blue => 34 }
ACTION_COLORS = {
:error => :red,
:warning => :yellow,
:info => :green,
:compile => :green,
:overwrite => :yellow,
:modified => :yellow,
:clean => :yellow,
:write => :green,
:create => :green,
:remove => :yellow,
:delete => :yellow,
:deleted => :yellow,
:created => :yellow,
:exists => :green,
:directory => :green,
:identical => :green,
:convert => :green,
:unchanged => :yellow
}
DEFAULT_ACTIONS = ACTION_COLORS.keys
ACTION_CAN_BE_QUIET = {
:error => false,
:warning => true,
:info => true,
:compile => true,
:overwrite => true,
:modified => true,
:clean => true,
:write => true,
:create => true,
:remove => true,
:delete => true,
:deleted => true,
:created => true,
:exists => true,
:directory => true,
:identical => true,
:convert => true,
:unchanged => true
}
attr_accessor :actions, :options, :time
def initialize(*actions)
self.options = actions.last.is_a?(Hash) ? actions.pop : {}
@actions = DEFAULT_ACTIONS.dup
@actions += actions
end
# Record an action that has occurred
def record(action, *arguments)
return if options[:quiet] && ACTION_CAN_BE_QUIET[action]
msg = ""
if time
msg << Time.now.strftime("%I:%M:%S.%3N %p")
end
msg << color(ACTION_COLORS[action]) if Compass.configuration.color_output
msg << "#{action_padding(action)}#{action}"
msg << color(:clear) if Compass.configuration.color_output
msg << " #{arguments.join(' ')}"
log msg
end
def green
wrap(:green) { yield }
end
def red
wrap(:red) { yield }
end
def yellow
wrap(:yellow) { yield }
end
def wrap(c, reset_to = :clear)
$stderr.write(color(c))
$stdout.write(color(c))
yield
ensure
$stderr.write(color(reset_to))
$stdout.write(color(reset_to))
$stdout.flush
end
def color(c)
if Compass.configuration.color_output && c && COLORS.has_key?(c.to_sym)
if defined?($boring) && $boring
""
else
"\e[#{COLORS[c.to_sym]}m"
end
else
""
end
end
# Emit a log message without a trailing newline
def emit(msg)
print msg
$stdout.flush
end
# Emit a log message with a trailing newline
def log(msg)
puts msg
$stdout.flush
end
# add padding to the left of an action that was performed.
def action_padding(action)
' ' * [(max_action_length - action.to_s.length), 0].max
end
# the maximum length of all the actions known to the logger.
def max_action_length
@max_action_length ||= actions.inject(0){|memo, a| [memo, a.to_s.length].max}
end
end
class NullLogger < Logger
def record(*args)
end
def log(msg)
end
def emit(msg)
end
end
end
================================================
FILE: cli/lib/compass/quick_cache.rb
================================================
module QuickCache
# cache a value in memory for just a few seconds
# This can speed up reads of values that change relatively infrequently
# but might be read many times in a short burst of reads.
def quick_cache(key, ttl = 1)
@quick_cache ||= {}
if @quick_cache[key] && @quick_cache[key].first > Time.now - ttl
@quick_cache[key].last
else
(@quick_cache[key] = [Time.now, yield]).last
end
end
end
================================================
FILE: cli/lib/compass/rails.rb
================================================
# Rails requires compass by requiring this file.
require 'compass'
================================================
FILE: cli/lib/compass/sass_compiler.rb
================================================
require 'sass/plugin'
class Compass::SassCompiler
include Compass::Actions
attr_writer :logger
attr_reader :quiet
attr_reader :error_count
attr_accessor :config
attr_accessor :display_compilation_times
attr_accessor :working_path
attr_accessor :only_sass_files
def initialize(options = {}, config = Compass.configuration)
options = options.dup
self.config = config
self.display_compilation_times = options.delete(:time)
self.working_path = options.delete(:working_path) || Dir.pwd
self.only_sass_files = options.delete(:only_sass_files) || []
@quiet = options[:quiet]
plugin_options = config.to_sass_plugin_options.merge(options)
if only_sass_files.any?
plugin_options[:template_location] = []
plugin_options[:load_paths] = config.sass_load_paths
end
plugin_options[:always_update] = true if options.delete(:force)
plugin_options[:compass] ||= {}
plugin_options[:compass][:logger] = logger
@compiler = Sass::Plugin::Compiler.new(plugin_options)
@start_times = {}
@error_count = 0
public_methods(true).grep(/^when_/).each do |callback|
@compiler.send(callback.to_s.sub(/^when_/, 'on_')) {|*args| send(callback, *args) }
end
end
def compile!
@compiler.update_stylesheets(individual_files)
end
def watch!(options = {}, &block)
skip_initial_update = options.fetch(:skip_initial_update, false)
begin
@compiler.watch(individual_files, options.merge(:skip_initial_update => skip_initial_update), &block)
rescue Sass::SyntaxError => e
skip_initial_update = true
retry
end
end
def individual_files
only_sass_files.map {|sass_file| [sass_file, corresponding_css_file(sass_file)]}
end
def clean!
@compiler.clean(individual_files)
end
def file_list
@compiler.file_list(individual_files)
end
def when_updating_stylesheets(individual_files)
@start_times = {}
@error_count = 0
end
def when_compilation_starting(sass_file, css, sourcemap)
@start_times[sass_file] = Time.now
end
def when_template_created(sass_file)
logger.record :created, relativize(sass_file)
end
def when_template_deleted(sass_file)
logger.record :deleted, relativize(sass_file)
end
def when_template_modified(sass_file)
logger.record :modified, relativize(sass_file)
end
def when_updated_stylesheet(sass_file, css, sourcemap)
if css && display_compilation_times && @start_times[sass_file]
duration = ((Time.now - @start_times[sass_file]) * 1000).round / 1000.0
logger.record :write, "#{relativize(css)} (#{duration}s)"
else
logger.record :write, relativize(css) if css
end
config.run_stylesheet_saved(css) if css
logger.record :write, relativize(sourcemap) if sourcemap
config.run_sourcemap_saved(sourcemap) if sourcemap
end
def when_creating_directory(dirname)
logger.record :directory, relativize(dirname)
end
def when_deleting_css(filename)
logger.record :delete, relativize(filename)
config.run_stylesheet_removed(filename) if filename
end
def when_deleting_sourcemap(filename)
logger.record :delete, relativize(filename)
config.run_sourcemap_removed(filename) if filename
end
def when_compilation_error(error, sass_file, css_file, sourcemap_file)
@error_count += 1
if error.respond_to?(:sass_filename)
error_filename = error.sass_filename || sass_file
if relativize(error_filename) == relativize(sass_file)
logger.record :error, "#{relativize(sass_file)} (Line #{error.sass_line}: #{error.message})"
else
logger.record :error, "#{relativize(sass_file)} (Line #{error.sass_line} of #{relativize(error_filename)}: #{error.message})"
end
else
logger.record :error, "#{relativize(sass_file)} (#{error.backtrace.first}: #{error.message})"
end
config.run_stylesheet_error(sass_file, error.message)
end
def logger
@logger ||= Compass::Logger.new(:quiet => quiet)
end
def corresponding_css_file(sass_file)
"#{config.css_path}/#{stylesheet_name(sass_file)}.css"
end
def stylesheet_name(sass_file)
if sass_file.index(config.sass_path) == 0
sass_file[(config.sass_path.length + 1)..-6].sub(/\.css$/,'')
else
raise Compass::Error, "Individual stylesheets must be in the sass directory."
end
end
def sass_files(options = {})
@compiler.template_location_array.map do |(sass_dir, css_dir)|
glob = options[:include_partials] ?
File.join("**","*.s[ac]ss*") :
File.join("**","[^_]*.s[ac]ss*")
Dir.glob(File.join(sass_dir, glob))
end.flatten
end
end
================================================
FILE: cli/lib/compass/sass_extensions/functions/sprites.rb
================================================
module Compass::SassExtensions::Functions::Sprites
extend Compass::SassExtensions::Functions::SassDeclarationHelper
extend Sass::Script::Value::Helpers
include Sass::Script::Value::Helpers
ZERO = number(0)
BOOL_FALSE = bool(false)
VALID_SELECTORS = %w(hover active target focus)
# Provides a consistent interface for getting a variable in ruby
# from a keyword argument hash that accounts for underscores/dash equivalence
# and allows the caller to pass a symbol instead of a string.
module VariableReader
def get_var(variable_name)
self[variable_name.to_s.gsub(/-/,"_")]
end
end
# Returns the width of the generated sprite map
def sprite_width(map, sprite=nil)
verify_map(map, 'sprite-width')
file = get_sprite_file(map, sprite)
width, _ = image_dimensions(file)
number(width, "px")
end
declare :sprite_width, [:map]
declare :sprite_width, [:map, :sprite]
# Returns the height of the generated sprite map
def sprite_height(map, sprite=nil)
verify_map(map, 'sprite-height')
file = get_sprite_file(map, sprite)
_, height = image_dimensions(file)
number(height, "px")
end
declare :sprite_height, [:map]
declare :sprite_height, [:map, :sprite]
# Returns a list of all sprite names
def sprite_names(map)
verify_map(map, 'sprite-names')
list(map.sprite_names.map { |f| identifier(f) }, :comma)
end
declare :sprite_names, [:map]
# Returns the system path of the sprite file
def sprite_path(map)
verify_map(map, 'sprite-path')
identifier(map.filename)
end
declare :sprite_path, [:map]
# Returns the sprite file as an inline image
# @include "icon/*.png";
# #{$icon-sprite-base-class} {
# background-image: inline-sprite($icon-sprites);
# }
def inline_sprite(map)
verify_map(map, "sprite-url")
map.generate
path = map.filename
inline_image_string(data(path), compute_mime_type(path))
end
declare :inline_sprite, [:map]
# Creates a Compass::SassExtensions::Sprites::SpriteMap object. A sprite map, when used in a property is the same
# as calling sprite-url. So the following background properties are equivalent:
#
# $icons: sprite-map("icons/*.png");
# background: sprite-url($icons) no-repeat;
# background: $icons no-repeat;
#
# The sprite map object will generate the sprite map image, if necessary,
# the first time it is converted to a url. Simply constructing it has no side-effects.
def sprite_map(glob, kwargs = {})
kwargs.extend VariableReader
Compass::SassExtensions::Sprites::SpriteMap.from_uri(glob, self, kwargs)
end
declare :sprite_map, [:glob], :var_kwargs => true
# Returns the image and background position for use in a single shorthand property:
#
# $icons: sprite-map("icons/*.png"); // contains icons/new.png among others.
# background: sprite($icons, new) no-repeat;
#
# Becomes:
#
# background: url('/images/icons.png?12345678') 0 -24px no-repeat;
#
# If the `use_percentages` parameter is passed as true, percentages will be
# used to position the sprite. Example output:
#
# background: url('/images/icons.png?12345678') 0 50% no-repeat;
#
def sprite(map, sprite, offset_x = ZERO, offset_y = ZERO, use_percentages = BOOL_FALSE)
sprite = convert_sprite_name(sprite)
verify_map(map)
verify_sprite(sprite)
url = sprite_url(map)
position = sprite_position(map, sprite, offset_x, offset_y, use_percentages)
list([url] + position.value, :space)
end
declare :sprite, [:map, :sprite]
declare :sprite, [:map, :sprite, :offset_x]
declare :sprite, [:map, :sprite, :offset_x, :offset_y]
declare :sprite, [:map, :sprite, :offset_x, :offset_y, :use_percentages]
# Returns the name of a sprite map
# The name is derived from the folder than contains the sprites.
def sprite_map_name(map)
verify_map(map, "sprite-map-name")
identifier(map.name)
end
declare :sprite_name, [:sprite]
# Returns the path to the original image file for the sprite with the given name
def sprite_file(map, sprite)
sprite = convert_sprite_name(sprite)
verify_map(map, "sprite")
verify_sprite(sprite)
if image = map.image_for(sprite.value)
image_path = Pathname.new(File.expand_path(image.file))
images_path = Pathname.new(File.expand_path(Compass.configuration.images_path))
quoted_string(image_path.relative_path_from(images_path).to_s)
else
missing_image!(map, sprite)
end
end
declare :sprite_file, [:map, :sprite]
# Returns boolean if sprite has a parent
def sprite_does_not_have_parent(map, sprite)
sprite = convert_sprite_name(sprite)
verify_map map
verify_sprite sprite
bool(map.image_for(sprite.value).parent.nil?)
end
declare :sprite_does_not_have_parent, [:map, :sprite]
#return the name of the selector file
def sprite_selector_file(map, sprite, selector)
sprite = convert_sprite_name(sprite)
image = map.image_for(sprite)
if map.send(:"has_#{selector.value}?", sprite.value)
return identifier(image.send(selector.value).name)
end
raise Sass::SyntaxError, "Sprite: #{sprite.value} does not have a #{selector} state"
end
declare :sprite_selector_file, [:map, :sprite, :selector]
# Returns boolean if sprite has the selector
def sprite_has_selector(map, sprite, selector)
sprite = convert_sprite_name(sprite)
verify_map map
verify_sprite sprite
unless VALID_SELECTORS.include?(selector.value)
raise Sass::SyntaxError, "Invalid Selctor did you mean one of: #{VALID_SELECTORS.join(', ')}"
end
bool map.send(:"has_#{selector.value}?", sprite.value)
end
declare :sprite_has_selector, [:map, :sprite, :selector]
# Determines if the CSS selector is valid
IDENTIFIER_RX = /\A#{Sass::SCSS::RX::IDENT}\Z/
def sprite_has_valid_selector(selector)
unless selector.value =~ IDENTIFIER_RX
raise Sass::SyntaxError, "#{selector} must be a legal css identifier"
end
bool true
end
# Returns a url to the sprite image.
def sprite_url(map)
verify_map(map, "sprite-url")
map.generate
generated_image_url(identifier("#{map.path}-s#{map.uniqueness_hash}.png"))
end
declare :sprite_url, [:map]
# Returns the position for the original image in the sprite.
# This is suitable for use as a value to background-position:
#
# $icons: sprite-map("icons/*.png");
# background-position: sprite-position($icons, new);
#
# Might generate something like:
#
# background-position: 0 -34px;
#
# You can adjust the background relative to this position by passing values for
# `$offset-x` and `$offset-y`:
#
# $icons: sprite-map("icons/*.png");
# background-position: sprite-position($icons, new, 3px, -2px);
#
# Would change the above output to:
#
# background-position: 3px -36px;
#
# If you set the `use_percentages` parameter to true, the position will be
# expressed in percentages. An example:
#
# background-position: sprite-position($icons, new, 0, 0, true);
#
# Would result in something like this:
#
# background-position: 0 42%;
#
def sprite_position(map, sprite = nil, offset_x = ZERO, offset_y = ZERO, use_percentages = BOOL_FALSE)
assert_type offset_x, :Number
assert_type offset_y, :Number
sprite = convert_sprite_name(sprite)
verify_map(map, "sprite-position")
unless sprite.is_a?(Sass::Script::Value::String) || sprite.is_a?(Sass::Script::Value::Number)
raise Sass::SyntaxError, %Q(The second argument to sprite-position must be a sprite name. See http://beta.compass-style.org/help/tutorials/spriting/ for more information.)
end
image = map.image_for(sprite.value)
unless image
missing_image!(map, sprite)
end
if use_percentages.value
xdivis = map.width - image.width;
x = (offset_x.value + image.left.to_f) / (xdivis.nonzero? || 1) * 100
x = x == 0 ? number(x) : number(x, "%")
ydivis = map.height - image.height;
y = (offset_y.value + image.top.to_f) / (ydivis.nonzero? || 1) * 100
y = y == 0 ? number(y) : number(y, "%")
else
if offset_x.unit_str == "%"
x = offset_x # CE: Shouldn't this be a percentage of the total width?
else
x = offset_x.value - image.left
x = x == 0 ? number(x) : number(x, "px")
end
y = offset_y.value - image.top
y = y == 0 ? number(y) : number(y, "px")
end
list(x, y, :space)
end
declare :sprite_position, [:map]
declare :sprite_position, [:map, :sprite]
declare :sprite_position, [:map, :sprite, :offset_x]
declare :sprite_position, [:map, :sprite, :offset_x, :offset_y]
declare :sprite_position, [:map, :sprite, :offset_x, :offset_y, :use_percentages]
protected
def get_sprite_file(map, sprite=nil)
if sprite
map.image_for(sprite).file
else
map.filename
end
end
def reversed_color_names
if Sass::Script::Value::Color.const_defined?(:HTML4_COLORS_REVERSE)
Sass::Script::Value::Color::HTML4_COLORS_REVERSE
else
Sass::Script::Value::Color::COLOR_NAMES_REVERSE
end
end
def convert_sprite_name(sprite)
case sprite
when Sass::Script::Value::Color
rgb = if reversed_color_names.keys.first.size == 3
sprite.rgb
else
# Sass 3.3 includes the alpha channel
sprite.rgba
end
identifier(reversed_color_names[rgb])
when Sass::Script::Value::Bool
identifier(sprite.to_s)
else
sprite
end
end
def verify_map(map, error = "sprite")
unless map.is_a?(Compass::SassExtensions::Sprites::SpriteMap)
missing_sprite!(error)
end
end
def verify_sprite(sprite)
unless sprite.is_a?(Sass::Script::Value::String) || sprite.is_a?(Sass::Script::Value::Number)
raise Sass::SyntaxError, %Q(The second argument to sprite() must be a sprite name. See http://beta.compass-style.org/help/tutorials/spriting/ for more information.)
end
end
def missing_image!(map, sprite)
raise Sass::SyntaxError, "No sprite called #{sprite} found in sprite map #{map.path}/#{map.name}. Did you mean one of: #{map.sprite_names.join(", ")}"
end
def missing_sprite!(function_name)
raise Sass::SyntaxError, %Q(The first argument to #{function_name}() must be a sprite map. See http://beta.compass-style.org/help/tutorials/spriting/ for more information.)
end
end
================================================
FILE: cli/lib/compass/sass_extensions/functions.rb
================================================
module Compass::SassExtensions::Functions
module SassDeclarationHelper
def declare(*args)
Sass::Script::Functions.declare(*args)
end
end
end
%w(sprites).each do |func|
require "compass/sass_extensions/functions/#{func}"
end
module Sass::Script::Functions
include Compass::SassExtensions::Functions::Sprites
end
================================================
FILE: cli/lib/compass/sass_extensions/sprites/engines/chunky_png_engine.rb
================================================
begin
require 'oily_png'
rescue LoadError
require 'chunky_png'
end
module Compass
module SassExtensions
module Sprites
class ChunkyPngEngine < Compass::SassExtensions::Sprites::Engine
def construct_sprite
@canvas = ChunkyPNG::Image.new(width, height, ChunkyPNG::Color::TRANSPARENT)
images.each do |image|
input_png = begin
ChunkyPNG::Image.from_file(image.file)
rescue ChunkyPNG::SignatureMismatch
raise Compass::SpriteException, "You have provided a file that does not have a PNG signature. Only PNG files are supported by the default sprite engine"
end
canvas.replace! input_png, image.left, image.top
end
end
def save(filename)
if canvas.nil?
construct_sprite
end
canvas.save(filename, Compass.configuration.chunky_png_options)
end
end
end
end
end
================================================
FILE: cli/lib/compass/sass_extensions/sprites/engines.rb
================================================
module Compass
module SassExtensions
module Sprites
class Engine
attr_accessor :width, :height, :images, :canvas
def initialize(width, height, images)
@width, @height, @images = width, height, images
@canvas = nil
end
def construct_sprite
raise ::Compass::Error, "You must implement construct_sprite"
end
def save(filename)
raise ::Compass::Error, "You must implement save(filename)"
end
end
end
end
end
require 'compass/sass_extensions/sprites/engines/chunky_png_engine'
================================================
FILE: cli/lib/compass/sass_extensions/sprites/image.rb
================================================
module Compass
module SassExtensions
module Sprites
class Image
include Sass::Script::Value::Helpers
ACTIVE = %r{[_-]active$}
TARGET = %r{[_-]target$}
HOVER = %r{[_-]hover$}
FOCUS = %r{[_-]focus$}
PARENT = %r{(.+)[-_](.+)$}
REPEAT_X = 'repeat-x'
REPEAT_Y = 'repeat-y'
NO_REPEAT = 'no-repeat'
VALID_REPEATS = [REPEAT_Y, REPEAT_X, NO_REPEAT]
attr_reader :relative_file, :options, :base, :name
attr_accessor :top, :left
def initialize(base, relative_file, options)
@base, @relative_file, @options = base, relative_file, options
@left = @top = 0
@name = File.basename(relative_file, '.png')
end
# The Full path to the image
def file
@file ||= find_file
end
def find_file
Compass.configuration.sprite_load_path.compact.each do |path|
f = File.join(path, relative_file)
if File.exists?(f)
return f
end
end
end
# Width of the image
def width
dimensions.first
end
def size
@size ||= File.size(file)
end
# Height of the image
def height
dimensions.last
end
def get_var_file(var)
options.get_var "#{base.name}_#{name}_#{var}"
end
# Value of $#{name}-repeat or $repeat
def repeat
@repeat ||= begin
rep = (get_var_file("repeat") || options.get_var("repeat") || identifier(NO_REPEAT)).value
unless VALID_REPEATS.include? rep
raise SpriteException, "Invalid option for repeat \"#{rep}\" - valid options are #{VALID_REPEATS.join(', ')}"
end
rep
end
end
def repeat_x?
repeat == REPEAT_X
end
def repeat_y?
repeat == REPEAT_Y
end
def no_repeat?
repeat == NO_REPEAT
end
# Value of $#{name}-position or $position defaults to 0px
def position
@position ||= get_var_file("position") || options.get_var("position") || number(0, "px")
end
# Offset within the sprite
def offset
@offset ||= (position.unitless? || position.unit_str == "px") ? position.value : 0
end
# Spacing between this image and the next
def spacing
@spacing ||= (get_var_file("spacing") || options.get_var("spacing") || number(0, 'px')).value
end
# MD5 hash of this file
def digest
Digest::MD5.file(file).hexdigest
end
# mtime of this file
def mtime
File.mtime(file)
end
# Is hover selector
def hover?
name =~ HOVER
end
# Hover selector Image object if exsists
def hover
base.get_magic_selector_image(name, 'hover')
end
# Is target selector
def target?
name =~ TARGET
end
# Target selector Image object if exsists
def target
base.get_magic_selector_image(name, 'target')
end
# Is active selector
def active?
name =~ ACTIVE
end
# Active selector Image object if exsists
def active
base.get_magic_selector_image(name, 'active')
end
# Is active selector
def focus?
name =~ FOCUS
end
# Active selector Image object if exsists
def focus
base.get_magic_selector_image(name, 'focus')
end
def parent
if [hover?, target?, active?, focus?].any?
PARENT.match name
base.image_for($1)
end
end
private
def dimensions
@dimensions ||= Compass::Core::SassExtensions::Functions::ImageSize::ImageProperties.new(file).size
end
end
end
end
end
================================================
FILE: cli/lib/compass/sass_extensions/sprites/image_methods.rb
================================================
module Compass
module SassExtensions
module Sprites
module ImageMethods
# Fetches the Sprite::Image object for the supplied name
def image_for(name)
if name.is_a?(Sass::Script::Value::String)
name = name.value
end
name = name.to_s
@images.detect { |img| img.name.downcase == name.downcase}
end
# Returns true if the image name has a hover selector image
def has_hover?(name)
!get_magic_selector_image(name, 'hover').nil?
end
# Returns true if the image name has a target selector image
def has_target?(name)
!get_magic_selector_image(name, 'target').nil?
end
# Returns true if the image name has a focus selector image
def has_focus?(name)
!get_magic_selector_image(name, 'focus').nil?
end
# Returns true if the image name has an active selector image
def has_active?(name)
!get_magic_selector_image(name, 'active').nil?
end
SEPERATORS = ['_', '-']
def get_magic_selector_image(name, selector)
SEPERATORS.each do |seperator|
file = image_for("#{name}#{seperator}#{selector}")
return file if !file.nil?
end
nil
end
# Return and array of image names that make up this sprite
def sprite_names
image_names.map { |f| File.basename(f, '.png') }
end
end
end
end
end
================================================
FILE: cli/lib/compass/sass_extensions/sprites/image_row.rb
================================================
require 'forwardable'
module Compass
module SassExtensions
module Sprites
class ImageRow
extend Forwardable
attr_reader :images, :max_width
def_delegators :@images, :last, :delete, :empty?, :length
def initialize(max_width)
@images = []
@max_width = max_width
end
def add(image)
return false if !will_fit?(image)
@images << image
true
end
alias :<< :add
def height
images.map(&:height).max
end
def width
images.map(&:width).max
end
def total_width
images.inject(0) {|sum, img| sum + img.width }
end
def efficiency
1 - (total_width.to_f / max_width.to_f)
end
def will_fit?(image)
(total_width + image.width) <= max_width
end
end
end
end
end
================================================
FILE: cli/lib/compass/sass_extensions/sprites/images.rb
================================================
module Compass
module SassExtensions
module Sprites
class Images < Array
def sort_by!(method)
invert = false
if method.to_s[0] == '!'[0] # have todo this for 1.8.7 compat
method = method.to_s[1..-1]
invert = true
end
method = method.to_sym
self.sort! do |a, b|
unless a.send(method) == b.send(method)
a.send(method) <=> b.send(method)
else
other = ([:size, :name] - [method]).first
a.send(other) <=> b.send(other)
end
end
self.reverse! if invert
end
end
end
end
end
================================================
FILE: cli/lib/compass/sass_extensions/sprites/layout/diagonal.rb
================================================
module Compass
module SassExtensions
module Sprites
module Layout
class Diagonal < SpriteLayout
def layout!
calculate_width!
calculate_height!
calculate_positions!
end
private # ===========================================================================================>
def calculate_width!
@width = @images.inject(0) {|sum, img| sum + img.width}
end
def calculate_height!
@height = @images.inject(0) {|sum, img| sum + img.height}
end
def calculate_positions!
previous = nil
@images.each_with_index do |image, index|
if previous.nil?
previous = image
image.top = @height - image.height
image.left = 0
next
end
image.top = previous.top - image.height
image.left = previous.left + previous.width
previous = image
end
end
end
end
end
end
end
================================================
FILE: cli/lib/compass/sass_extensions/sprites/layout/horizontal.rb
================================================
module Compass
module SassExtensions
module Sprites
module Layout
class Horizontal < SpriteLayout
def layout!
calculate_height!
calculate_width!
calculate_positions!
tile_images_that_repeat!
end
private # ===========================================================================================>
def calculate_height!
@height = @images.map {|image| image.height + image.offset}.max
if repeating_images?
calculate_repeat_extra_height!
end
@height
end
def calculate_width!
@width = @images.inject(0) { |sum, image| sum += (image.width + image.spacing) }
end
def repeating_images?
@repeating_images ||= @images.any?(&:repeat_y?)
end
def calculate_repeat_extra_height!
m = @images.inject(1) {|m,img| img.repeat_y? ? m.lcm(img.height) : m }
remainder = @height % m
@height += (m - remainder) unless remainder.zero?
end
def calculate_positions!
@images.each_with_index do |image, index|
image.top = image.position.unit_str == '%' ? (@height - image.height) * (image.position.value / 100.0) : image.position.value
next if index == 0
last_image = @images[index-1]
image.left = last_image.left + last_image.width + [image.spacing, last_image.spacing].max
end
end
def tile_images_that_repeat!
return unless repeating_images?
@images.map {|img| img if img.repeat_y?}.compact.each do |image|
y = (image.top + image.height)
while y < @height do
begin
img = image.dup
img.top = y.to_i
@images << img
y += image.height
end
end #while
end
end
end
end
end
end
end
================================================
FILE: cli/lib/compass/sass_extensions/sprites/layout/smart.rb
================================================
module Compass
module SassExtensions
module Sprites
module Layout
class Smart < SpriteLayout
def layout!
calculate_positions!
end
private # ===========================================================================================>
def calculate_positions!
fitter = ::Compass::SassExtensions::Sprites::RowFitter.new(@images)
current_y = 0
fitter.fit!.each do |row|
current_x = 0
row.images.each_with_index do |image, index|
image.left = current_x
image.top = current_y
current_x += image.width
end
current_y += row.height
end
@width = fitter.width
@height = fitter.height
end
end
end
end
end
end
================================================
FILE: cli/lib/compass/sass_extensions/sprites/layout/vertical.rb
================================================
module Compass
module SassExtensions
module Sprites
module Layout
class Vertical < SpriteLayout
def layout!
calculate_width!
calculate_positions!
calculate_height!
tile_images_that_repeat!
end
private # ===========================================================================================>
def calculate_width!
@width = @images.map { |image| image.width + image.offset }.max
if repeating_images?
calculate_repeat_extra_width!
end
@width
end
def calculate_height!
last = @images.last
@height = last.top + last.height
end
def repeating_images?
@repeating_images ||= @images.any?(&:repeat_x?)
end
def calculate_repeat_extra_width!
m = @images.inject(1) {|m,img| img.repeat_x? ? m.lcm(img.width) : m }
remainder = @width % m
@width += (m - remainder) unless remainder.zero?
end
def calculate_positions!
@images.each_with_index do |image, index|
image.left = (image.position.unit_str == "%" ? (@width - image.width) * (image.position.value / 100.0) : image.position.value).to_i
next if index == 0
last_image = @images[index-1]
image.top = last_image.top + last_image.height + [image.spacing, last_image.spacing].max
end #each_with_index
end #method
def tile_images_that_repeat!
return unless repeating_images?
@images.map {|img| img if img.repeat_x?}.compact.each do |image|
x = image.left - (image.left / image.width).ceil * image.width
while x < @width do
begin
img = image.dup
img.top = image.top
img.left = x.to_i
@images << img
x += image.width
end #begin
end #while
end #map
end #method
end #Vertical
end #Layout
end #Sprites
end #SassExtensions
end #Compass
================================================
FILE: cli/lib/compass/sass_extensions/sprites/layout.rb
================================================
require 'rational'
module Compass
module SassExtensions
module Sprites
module Layout
class SpriteLayout
attr_reader :images, :options
attr_accessor :height, :width
def initialize(images, kwargs={})
@images = images
@options = kwargs
@height = 0
@width = 0
layout!
end
def layout!
raise Compass::SpriteException, "You must impliment layout!"
end
def properties
if @width.zero?
raise Compass::SpriteException, "You must set the width fetching the properties"
end
if @height.zero?
raise Compass::SpriteException, "You must set the height fetching the properties"
end
[@images, @width, @height]
end
end
end
end
end
end
================================================
FILE: cli/lib/compass/sass_extensions/sprites/layout_methods.rb
================================================
module Compass
module SassExtensions
module Sprites
module LayoutMethods
HORIZONTAL = 'horizontal'
DIAGONAL = 'diagonal'
SMART = 'smart'
VERTICAL = 'vertical'
def smart?
layout == SMART
end
def horizontal?
layout == HORIZONTAL
end
def diagonal?
layout == DIAGONAL
end
def vertical?
layout == VERTICAL
end
def layout
@layout ||= @kwargs.get_var('layout').value
end
# Calculates the overal image dimensions
# collects image sizes and input parameters for each sprite
def compute_image_positions!
case layout
when SMART
require 'compass/sass_extensions/sprites/layout/smart'
@images, @width, @height = Layout::Smart.new(@images, @kwargs).properties
when DIAGONAL
require 'compass/sass_extensions/sprites/layout/diagonal'
@images, @width, @height = Layout::Diagonal.new(@images, @kwargs).properties
when HORIZONTAL
require 'compass/sass_extensions/sprites/layout/horizontal'
@images, @width, @height = Layout::Horizontal.new(@images, @kwargs).properties
else
require 'compass/sass_extensions/sprites/layout/vertical'
@images, @width, @height = Layout::Vertical.new(@images, @kwargs).properties
end
end
end
end
end
end
================================================
FILE: cli/lib/compass/sass_extensions/sprites/row_fitter.rb
================================================
require 'forwardable'
module Compass
module SassExtensions
module Sprites
class RowFitter
extend Forwardable
attr_reader :images, :rows
def_delegators :rows, :[]
def initialize(images)
@images = images.sort do |a,b|
if a.height == b.height
b.width <=> a.width
else
a.height <=> b.height
end
end
@rows = []
end
def fit!(style = :scan)
send("#{style}_fit")
@rows
end
def width
@width ||= @images.collect(&:width).max
end
def height
@height ||= @rows.inject(0) {|sum, row| sum += row.height}
end
def efficiency
@rows.inject(0) { |sum, row| sum += row.efficiency } ** @rows.length
end
private
def new_row(image = nil)
row = Compass::SassExtensions::Sprites::ImageRow.new(width)
row.add(image) if image
row
end
def fast_fit
row = new_row
@images.each do |image|
if !row.add(image)
@rows << row
row = new_row(image)
end
end
@rows << row
end
def scan_fit
fast_fit
moved_images = []
begin
removed = false
catch :done do
@rows.each do |row|
(@rows - [ row ]).each do |other_row|
other_row.images.each do |image|
if !moved_images.include?(image)
if row.will_fit?(image)
other_row.delete(image)
row << image
@rows.delete(other_row) if other_row.empty?
removed = true
moved_images << image
throw :done
end
end
end
end
end
end
end while removed
end
end
end
end
end
================================================
FILE: cli/lib/compass/sass_extensions/sprites/sprite_map.rb
================================================
module Compass
module SassExtensions
module Sprites
class SpriteMap < Sass::Script::Value::Base
attr_accessor :image_names, :path, :name, :map, :kwargs
attr_accessor :images, :width, :height, :engine
include SpriteMethods
include ImageMethods
include LayoutMethods
include Sass::Script::Value::Helpers
# Initialize a new sprite object from a relative file path
# the path is relative to the images_path confguration option
def self.from_uri(uri, context, kwargs)
uri = uri.value
path, name = Compass::SpriteImporter.path_and_name(uri)
files = Compass::SpriteImporter.files(uri)
sprites = files.map do |sprite|
relative_name(sprite)
end
new(sprites, path, name, context, kwargs)
end
def self.relative_name(sprite)
sprite = File.expand_path(sprite)
Compass.configuration.sprite_load_path.each do |path|
path_with_slash = "#{File.expand_path(path)}/"
if sprite.include?(path_with_slash)
return sprite.gsub(path_with_slash, '')
end
end
end
def initialize(sprites, path, name, context, kwargs)
@image_names = sprites
@path = path
@name = name
@kwargs = kwargs
@kwargs['cleanup'] ||= bool(true)
@kwargs['layout'] ||= identifier('vertical')
@kwargs['sort_by'] ||= identifier('none')
@images = nil
@width = nil
@height = nil
@engine = nil
@evaluation_context = context
compute_image_metadata!
end
def sort_method
@kwargs['sort_by'].value
end
def inspect
puts 'images'
@images.each do |img|
puts img.file
end
puts "options"
@kwargs.each do |k,v|
puts "#{k}:#{v}"
end
end
def to_s(kwargs = self.kwargs)
sprite_url(self).value
end
def respond_to?(meth)
super || @evaluation_context.respond_to?(meth)
end
def method_missing(meth, *args, &block)
if @evaluation_context.respond_to?(meth)
@evaluation_context.send(meth, *args, &block)
else
super
end
end
private
def modulize
@modulize ||= Compass::configuration.sprite_engine.to_s.scan(/([^_.]+)/).flatten.map {|chunk| "#{chunk[0].chr.upcase}#{chunk[1..-1]}" }.join
end
end
end
end
end
================================================
FILE: cli/lib/compass/sass_extensions/sprites/sprite_methods.rb
================================================
module Compass
module SassExtensions
module Sprites
module SpriteMethods
# Changing this string will invalidate all previously generated sprite images.
# We should do so only when the packing algorithm changes
SPRITE_VERSION = "2"
# Calculates the overal image dimensions
# collects image sizes and input parameters for each sprite
# Calculates the height
def compute_image_metadata!
@width = 0
init_images
compute_image_positions!
init_engine
end
def init_engine
@engine = eval("::Compass::SassExtensions::Sprites::#{modulize}Engine.new(nil, nil, nil)")
@engine.width = @width
@engine.height = @height
@engine.images = @images
end
# Creates the Sprite::Image objects for each image and calculates the width
def init_images
@images = Images.new
image_names.each do |relative_file|
@images << Image.new(self, relative_file, kwargs)
end
unless sort_method == 'none'
@images.sort_by! sort_method
end
end
def name_and_hash
"#{path}-s#{uniqueness_hash}.png"
end
# The on-the-disk filename of the sprite
def filename
File.join(Compass.configuration.generated_images_path, name_and_hash)
end
def relativize(path)
Pathname.new(path).relative_path_from(Pathname.new(Dir.pwd)).to_s rescue path
end
# Generate a sprite image if necessary
def generate
if generation_required?
if kwargs.get_var('cleanup').value
cleanup_old_sprites
end
engine.construct_sprite
Compass.configuration.run_sprite_generated(engine.canvas)
save!
else
log :unchanged, filename
end
end
def cleanup_old_sprites
Sass::Util.glob(File.join(Compass.configuration.generated_images_path, "#{path}-s*.png")).each do |file|
log :remove, file
FileUtils.rm file
Compass.configuration.run_sprite_removed(file)
end
end
# Does this sprite need to be generated
def generation_required?
!File.exists?(filename) || outdated? || options[:force]
end
# Returns the uniqueness hash for this sprite object
def uniqueness_hash
@uniqueness_hash ||= begin
sum = Digest::MD5.new
sum << SPRITE_VERSION
sum << path
sum << layout
images.each do |image|
[:relative_file, :height, :width, :repeat, :spacing, :position, :digest].each do |attr|
sum << image.send(attr).to_s
end
end
sum.hexdigest[0...10]
end
@uniqueness_hash
end
# Saves the sprite engine
def save!
FileUtils.mkdir_p(File.dirname(filename))
saved = engine.save(filename)
log :create, filename
Compass.configuration.run_sprite_saved(filename)
@mtime = nil if saved
saved
end
# All the full-path filenames involved in this sprite
def image_filenames
@images.map(&:file)
end
# Checks whether this sprite is outdated
def outdated?
if File.exists?(filename)
return @images.any? {|image| image.mtime.to_i > self.mtime.to_i }
end
true
end
# Mtime of the sprite file
def mtime
@mtime ||= File.mtime(filename)
end
# Calculate the size of the sprite
def size
[width, height]
end
def log(action, filename, *extra)
if options[:compass] && options[:compass][:logger] && !options[:quiet]
options[:compass][:logger].record(action, relativize(filename), *extra)
end
end
end
end
end
end
================================================
FILE: cli/lib/compass/sass_extensions/sprites.rb
================================================
require 'digest/md5'
require 'compass/sprite_importer'
module Compass
module SassExtensions
module Sprites
end
end
end
require 'compass/sass_extensions/sprites/images'
require 'compass/sass_extensions/sprites/layout'
require 'compass/sass_extensions/sprites/image_row'
require 'compass/sass_extensions/sprites/row_fitter'
require 'compass/sass_extensions/sprites/image'
require 'compass/sass_extensions/sprites/layout_methods'
require 'compass/sass_extensions/sprites/sprite_methods'
require 'compass/sass_extensions/sprites/image_methods'
require 'compass/sass_extensions/sprites/sprite_map'
require 'compass/sass_extensions/sprites/engines'
================================================
FILE: cli/lib/compass/sass_extensions.rb
================================================
unless Sass::Script::Functions.methods.grep(/\Adeclare\Z/).any?
raise LoadError, "It looks like you've got an incompatible version of Sass. This often happens when you have an old haml gem installed. Please upgrade Haml to v3.1 or above."
end
module Compass::SassExtensions
end
require 'compass/sass_extensions/functions'
require 'compass/sass_extensions/sprites'
================================================
FILE: cli/lib/compass/sprite_importer/binding.rb
================================================
require 'ostruct'
module Compass
module Sprites
class Binding < OpenStruct
def get_binding
binding
end
end
end
end
================================================
FILE: cli/lib/compass/sprite_importer/content.erb
================================================
@import "compass/utilities/sprites/base";
// General Sprite Defaults
// You can override them before you import this file.
$<%= name %>-sprite-dimensions : false !default;
$<%= name %>-use-percentages : false !default;
$<%= name %>-position : 0% !default;
$<%= name %>-spacing : 0 !default;
$<%= name %>-repeat : no-repeat !default;
$<%= name %>-prefix : '' !default;
$<%= name %>-clean-up : true !default;
$<%= name %>-layout : vertical !default;
$<%= name %>-inline : false !default;
$<%= name %>-sort-by : 'none' !default;
$<%= name %>-class-separator : $default-sprite-separator !default;
$<%= name %>-sprite-base-class : ".<%= name %>#{$<%= name %>-class-separator}sprite" !default;
<% if skip_overrides %>
$<%= name %>-sprites: sprite-map("<%= uri %>", $layout: $<%= name %>-layout, $cleanup: $<%= name %>-clean-up, $spacing: $<%= name %>-spacing, $position : $<%= name %>-position);
<% else %>
// These variables control the generated sprite output
// You can override them selectively before you import this file.
<% sprite_names.each do |sprite_name| %>
$<%= name %>-<%= sprite_name %>-position: $<%= name %>-position !default;
$<%= name %>-<%= sprite_name %>-spacing: $<%= name %>-spacing !default;
$<%= name %>-<%= sprite_name %>-repeat: $<%= name %>-repeat !default;
<% end %>
$<%= name %>-sprites: sprite-map("<%= uri %>",
<% sprite_names.each do |sprite_name| %>
$<%= name %>-<%= sprite_name %>-position: $<%= name %>-<%= sprite_name %>-position,
$<%= name %>-<%= sprite_name %>-spacing: $<%= name %>-<%= sprite_name %>-spacing,
$<%= name %>-<%= sprite_name %>-repeat: $<%= name %>-<%= sprite_name %>-repeat,
<% end %>
$layout : $<%= name %>-layout,
$cleanup : $<%= name %>-clean-up,
$spacing : $<%= name %>-spacing,
$position : $<%= name %>-position,
$sort-by : $<%= name %>-sort-by
);
<% end %>
// All sprites should extend this class
// The <%= name %>-sprite mixin will do so for you.
@if $<%= name %>-inline {
#{$<%= name %>-sprite-base-class} {
background-image: inline-sprite($<%= name %>-sprites);
}
} @else {
#{$<%= name %>-sprite-base-class} {
background-image: sprite-url($<%= name %>-sprites);
background-repeat: no-repeat;
}
}
//sass functions to return the dimensions of a sprite image as units
<% [:width, :height].each do |dimension| %>
@function <%= name %>-sprite-<%= dimension %>($name) {
@return sprite-<%= dimension %>($<%= name %>-sprites, $name);
}
<% end %>
// Use this to set the dimensions of an element
// based on the size of the original image.
@mixin <%= name %>-sprite-dimensions($name) {
@include sprite-dimensions($<%= name %>-sprites, $name)
}
// Move the background position to display the sprite.
@mixin <%= name %>-sprite-position($name, $offset-x: 0, $offset-y: 0, $use-percentages: $<%= name %>-use-percentages) {
@include sprite-background-position($<%= name %>-sprites, $name, $offset-x, $offset-y, $use-percentages)
}
// Extends the sprite base class and set the background position for the desired sprite.
// It will also apply the image dimensions if $dimensions is true.
@mixin <%= name %>-sprite($name, $dimensions: $<%= name %>-sprite-dimensions, $offset-x: 0, $offset-y: 0, $use-percentages: $<%= name %>-use-percentages, $separator: $<%= name %>-class-separator) {
@extend #{$<%= name %>-sprite-base-class};
@include sprite($<%= name %>-sprites, $name, $dimensions, $offset-x, $offset-y, $use-percentages, $separator: $separator);
}
@mixin <%= name %>-sprites($sprite-names, $dimensions: $<%= name %>-sprite-dimensions, $prefix: sprite-map-name($<%= name %>-sprites), $offset-x: 0, $offset-y: 0, $use-percentages: $<%= name %>-use-percentages, $separator: $<%= name %>-class-separator) {
@include sprites($<%= name %>-sprites, $sprite-names, $<%= name %>-sprite-base-class, $dimensions, $prefix, $offset-x, $offset-y, $use-percentages, $separator: $separator)
}
// Generates a class for each sprited image.
@mixin all-<%= name %>-sprites($dimensions: $<%= name %>-sprite-dimensions, $prefix: sprite-map-name($<%= name %>-sprites), $offset-x: 0, $offset-y: 0, $use-percentages: $<%= name %>-use-percentages, $separator: $<%= name %>-class-separator) {
@include <%= name %>-sprites(<%= sprite_names.join(" ") %>, $dimensions, $prefix, $offset-x, $offset-y, $use-percentages, $separator: $separator);
}
================================================
FILE: cli/lib/compass/sprite_importer.rb
================================================
require 'erb'
require 'compass/sprite_importer/binding'
module Compass
class SpriteImporter < Sass::Importers::Base
VAILD_FILE_NAME = /\A#{Sass::SCSS::RX::IDENT}\Z/
SPRITE_IMPORTER_REGEX = %r{((.+/)?([^\*.]+))/(.+?)\.png}
VALID_EXTENSIONS = ['.png']
TEMPLATE_FOLDER = File.join(File.expand_path('../', __FILE__), 'sprite_importer')
CONTENT_TEMPLATE_FILE = File.join(TEMPLATE_FOLDER, 'content.erb')
CONTENT_TEMPLATE = ERB.new(File.read(CONTENT_TEMPLATE_FILE))
# finds all sprite files
def self.find_all_sprite_map_files(path)
hex = "[0-9a-f]"
glob = "*-s#{hex*10}{#{VALID_EXTENSIONS.join(",")}}"
Sass::Util.glob(File.join(path, "**", glob))
end
def find(uri, options)
if uri =~ SPRITE_IMPORTER_REGEX
return self.class.sass_engine(uri, self.class.sprite_name(uri), self, options)
end
nil
end
def find_relative(uri, base, options)
nil
end
def to_s
self.class.name
end
def hash
self.class.name.hash
end
def eql?(other)
other.class == self.class
end
def mtime(uri, options)
self.class.files(uri).sort.inject(Time.at(0)) do |max_time, file|
(t = File.mtime(file)) > max_time ? t : max_time
end
end
def key(uri, options={})
[self.class.name + ":sprite:" + File.dirname(File.expand_path(uri)), File.basename(uri)]
end
def public_url(*args)
nil
end
def self.path_and_name(uri)
if uri =~ SPRITE_IMPORTER_REGEX
[$1, $3]
else
raise Compass::Error, "invalid sprite path"
end
end
# Name of this spite
def self.sprite_name(uri)
_, name = path_and_name(uri)
name
end
# The on-disk location of this sprite
def self.path(uri)
path, _ = path_and_name(uri)
path
end
# Returns the Glob of image files for the uri
def self.files(uri)
Compass.configuration.sprite_load_path.compact.each do |folder|
files = Sass::Util.glob(File.join(folder, uri)).sort
next if files.empty?
return files
end
path = Compass.configuration.sprite_load_path.to_a.join(', ')
raise Compass::SpriteException, %Q{No files were found in the load path matching "#{uri}". Your current load paths are: #{path}}
end
# Returns an Array of image names without the file extension
def self.sprite_names(uri)
files(uri).collect do |file|
File.basename(file, '.png')
end
end
# Returns the sass_options for this sprite
def self.sass_options(uri, importer, options)
options.merge!(:filename => uri.gsub(%r{\*/},"*\\/"), :syntax => :scss, :importer => importer)
end
# Returns a Sass::Engine for this sprite object
def self.sass_engine(uri, name, importer, options)
content = content_for_images(uri, name, options[:skip_overrides])
Sass::Engine.new(content, sass_options(uri, importer, options))
end
# Generates the Sass for this sprite file
def self.content_for_images(uri, name, skip_overrides = false)
binder = Compass::Sprites::Binding.new(:name => name, :uri => uri, :skip_overrides => skip_overrides, :sprite_names => sprite_names(uri), :files => files(uri))
CONTENT_TEMPLATE.result(binder.get_binding)
end
end
end
================================================
FILE: cli/lib/compass/stats.rb
================================================
module Compass
module Stats
class StatsVisitor
attr_accessor :rule_count, :prop_count, :mixin_def_count, :mixin_count
def initialize
self.rule_count = 0
self.prop_count = 0
self.mixin_def_count = 0
self.mixin_count = 0
end
def visit(node)
self.prop_count += 1 if node.is_a?(Sass::Tree::PropNode) && !node.children.any?
if node.is_a?(Sass::Tree::RuleNode)
self.rule_count += node.rule.reject{|r| r.is_a?(Sass::Script::Tree::Node)}.map{|r| r.split(/,/)}.flatten.compact.size
end
self.mixin_def_count += 1 if node.is_a?(Sass::Tree::MixinDefNode)
self.mixin_count += 1 if node.is_a?(Sass::Tree::MixinNode)
end
def up(node)
end
def down(node)
end
def import?(node)
return false
full_filename = node.send(:import)
full_filename != Compass.deprojectize(full_filename)
end
end
class CssFile
attr_accessor :path, :css
attr_accessor :selector_count, :prop_count
attr_accessor :file_size
def initialize(path)
require 'css_parser'
self.path = path
self.css = CssParser::Parser.new
self.css.add_block!(contents)
self.selector_count = 0
self.prop_count = 0
end
def contents
@contents ||= File.read(path)
end
def lines
contents.inject(0){|m,c| m + 1 }
end
def analyze!
self.file_size = File.size(path)
css.each_selector do |selector, declarations, specificity|
sels = selector.split(/,/).size
props = declarations.split(/;/).size
self.selector_count += sels
self.prop_count += props
end
end
end
class SassFile
attr_accessor :path
attr_reader :visitor
attr_accessor :file_size
def initialize(path)
self.path = path
end
def contents
@contents ||= File.read(path)
end
def tree
opts = Compass.configuration.to_sass_engine_options
opts[:syntax] = path[-4..-1].to_sym
@tree = Sass::Engine.new(contents, opts).to_tree
end
def visit_tree!
@visitor = StatsVisitor.new
tree.visit_depth_first(@visitor)
@visitor
end
def analyze!
self.file_size = File.size(path)
visit_tree!
end
def lines
contents.inject(0){|m,c| m + 1 }
end
def rule_count
visitor.rule_count
end
def prop_count
visitor.prop_count
end
def mixin_def_count
visitor.mixin_def_count
end
def mixin_count
visitor.mixin_count
end
end
end
end
================================================
FILE: cli/lib/compass/test_case.rb
================================================
module Compass
# Write your unit test like this if you want to make sure all your stylesheets compile.
#
# require 'compass/test_case'
# class StylesheetsTest < Compass::TestCase
# def test_stylesheets
# my_sass_files.each do |sass_file|
# assert_compiles(sass_file) do |result|
# assert_not_blank result
# end
# end
# end
# protected
# def my_sass_files
# Dir.glob(File.expand_path(File.join(File.dirname(__FILE__), "../..", "app/stylesheets/**/[^_]*.sass")))
# end
# end
class TestCase < (defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase)
def setup
super
@last_compile = nil
end
def compile(stylesheet)
input = open(stylesheet)
template = input.read()
input.close()
@last_compile = ::Sass::Engine.new(template, ::Sass::Plugin.engine_options(:filename => stylesheet)).render
yield @last_compile if block_given?
end
def assert_compiles(stylesheet, &block)
compile(stylesheet, &block)
end
end
end
================================================
FILE: cli/lib/compass/validator.rb
================================================
begin
require 'rubygems'
require 'compass-validator'
rescue LoadError => e
if e.message =~ /core_ext/
raise Compass::MissingDependency, <<-ERRORMSG
The Compass CSS Validator is out of date. Please upgrade it:
sudo gem install compass-validator --version ">= 3.0.1"
ERRORMSG
else
raise Compass::MissingDependency, <<-ERRORMSG
The Compass CSS Validator could not be loaded. Please install it:
sudo gem install compass-validator
ERRORMSG
end
end
================================================
FILE: cli/lib/compass/version.rb
================================================
require 'compass/generated_version'
module Compass
module Version
def scope(file) # :nodoc:
File.join(File.dirname(__FILE__), '..', '..', file)
end
def parse_version(version, name)
nil_or_int = lambda{|i| i.nil? ? nil : i.to_i}
segments = version.split(".")
{
:string => version,
:name => name,
:major => nil_or_int.call(segments.shift),
:minor => nil_or_int.call(segments.shift),
:patch => nil_or_int.call(segments.shift),
:state => segments.shift,
:iteration => nil_or_int.call(segments.shift)
}
end
# Returns a hash representing the version.
# The :major, :minor, and :teeny keys have their respective numbers.
# The :string key contains a human-readable string representation of the version.
# The :rev key will have the current revision hash.
#
# This method swiped from Haml and then modified, some credit goes to Nathan Weizenbaum
def version
Compass::VERSION_DETAILS
end
end
extend Compass::Version
unless defined?(::Compass::VERSION)
VERSION = File.read(scope("VERSION")).strip
VERSION_NAME = File.read(scope("VERSION_NAME")).strip
end
VERSION_DETAILS = parse_version(VERSION, VERSION_NAME)
end
================================================
FILE: cli/lib/compass.rb
================================================
module Compass
end
%w(core
deprecation
dependencies
sass_extensions
version
errors
quick_cache
logger
actions
).each do |lib|
require "compass/#{lib}"
end
require 'sass/callbacks'
module Compass
def base_directory
File.expand_path(File.join(File.dirname(__FILE__), '..'))
end
def lib_directory
File.expand_path(File.join(File.dirname(__FILE__)))
end
module_function :base_directory, :lib_directory
extend QuickCache
end
%w(configuration/helpers
configuration/comments
configuration/serialization
configuration/file_data
app_integration
compiler
sprite_importer
).each do |lib|
require "compass/#{lib}"
end
================================================
FILE: cli/test/fixtures/extensions/only_stylesheets/compass_init.rb
================================================
Compass::Frameworks.register("only-stylesheets", :stylesheets_dir => File.join(File.dirname(__FILE__),"scss"))
================================================
FILE: cli/test/fixtures/extensions/only_stylesheets/scss/only_stylesheets/foo.scss
================================================
@mixin only-stylesheets {
color: red;
}
================================================
FILE: cli/test/fixtures/fonts/bgrove.base64.txt
================================================
AAEAAAAOAIAAAwBgRkZUTVRX4doAAEkcAAAAHE9TLzJXOYGVAAABaAAAAFZjbWFwo9b83AAAA5wAAAGCY3Z0IAAhAnkAAAUgAAAABGdhc3D//wADAABJFAAAAAhnbHlmHjQt6QAABhQAADqcaGVhZO/rWMkAAADsAAAANmhoZWEG3gJsAAABJAAAACRobXR44bASCgAAAcAAAAHca2VybgkODBcAAECwAAACpmxvY2FEK1KSAAAFJAAAAPBtYXhwAMYAngAAAUgAAAAgbmFtZXbvKHoAAENYAAAD/3Bvc3Q8IkO/AABHWAAAAbwAAQAAAAYAAJqBq3tfDzz1AAsD6AAAAADG9QrgAAAAAMb1CuD/C/6AA9IDpAAAAAgAAgAAAAAAAAABAAADpP6AAFoD/v8L/3YD0gABAAAAAAAAAAAAAAAAAAAAdwABAAAAdwBtAA0AAAAAAAIAAAABAAEAAABAAC4AAAAAAAEB1gH0AAUACAKKArsAAACMAooCuwAAAd8AMQECAAACAAYDAAAAAAAAAAAAAwAAAAgAAAAAAAAAAFBmRWQAQAAgISIC7v8GAFoDpAGAAAAAAQAAAAAAAAFsACECrwA8AU0AAAGqAAAAxwAuARUANAIZAC8CKQAoApsAKwI4ACgAkQA0ANoANADa/9MB7wAuAe8ALwC2//4B7wAvAMcALgIzAC4CAAA0AUkAKAHtACgB5wAoAggAKAHzADQB9AA0Aj4ALgIVACgB6wArAL8AKgC4//4B4QAoAe8ALwHhAC4B5wAoApcAKAKvADQCpQA0Ak4AKAJAADQB+QA0AfkANAKGACgCqQA0AUMALgJNACgCYAA0AfgANAKtADQCAQA0ApcAKAHzADQCmwAoAfkANAIqACgB8wAuAq8ANAKpAC4CsAA0AgQALgKrADICCwAsAJYANAIzAC4Alf+6AfAALQHXACkAhQAuAfQAKAH0ADQBpwAoAfMAKAHnACgCUwAuAfQAKAIAADQBQwAuAOv/HwH3ADQBQwAuArUAPAH/ADQB5wAoAfMANAHsACgB2QA0AZ4ALQH0AC4B/wA0AiQALQKwADQB8gAuAgAANAHzAC4BGQAtAKEAPAEZ/7gBvQAyALsAMAGnADAAmQBCAf4APAKjADACuQA8AU8AKgH/ADYB5wAwAfEANgH+ADwB8gA2AgwANAMuADwD/gAwAVMANgDZ/wwCiAA8AqUALgK0ADYCvwA8AAAAAwAAAAMAAAAcAAEAAAAAAHwAAwABAAAAHAAEAGAAAAAUABAAAwAEAAAAfgCiAKcAqQCuALEAvyEi//8AAAAAACAAoQCmAKkArgCwAL8hIv//AAH/4//B/77/vf+5/7j/q99OAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQYAAAEAAAAAAAAAAQIAAAACAAAAAAAAAAAAAAAAAAAAAQAAAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaGMAZQAAAGdmcAAAAAAAAGkAAAAAAAAAAAAAAAAAAGpiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhAnkAAAAqAFwAXABcAIYAogEqAaYB8AJQAmICjAK2A0ADcgOgA7YD1APyBDwEcgS8BSAFZgWuBfQGOAZ+BtIHCAdQB4IHpgfYCCoIogjQCS4JXgmQCcwKDApUCpIKvgr2Cz4Lbgu4C/YMGAxODKYM/g1KDXYNog3YDiYOdg66DwgPMA9OD3YPrg/CD9QQChBKEH4QvBD6EToRhhHCEhISXhKoEtQTJBNSE3ITshP2FDAUdBSwFOYVEhVaFc4WGBZoFqgWuhcEF0IXaheyF84YMBh8GNAY7hkuGX4ZshnoGhwaVhqqGx4bbhvAHC4cjBzWHU4AAgAhAAABKgKaAAMABwAusQEALzyyBwQA7TKxBgXcPLIDAgDtMgCxAwAvPLIFBADtMrIHBgH8PLIBAgDtMjMRIREnMxEjIQEJ6MfHApr9ZiECWAAAAgA8//8ChQMZAA8AHwAAEyEyFhURFAYjISImNRE0NgUhIgYVERQWMyEyNjURNCaeAYUpOTkp/nsoOjoBrf57FyIiFwGFFyEhAxk5Kf2qKTk5KQJWKTkqIRf9qhchIRcCVhchAAMALv/kAJkDGQAJABMAGwAAExEUIyI1ETQzMgIyFhQGIyImNTQXIhUUMzI1NHgUFRUUKiwfHxYXHzYNDQwDB/2lERECWxL9Nh8uHh8WFwoNDAwNAAIANAIZAOEC8wAIABEAABMyHQEUIj0BNDMyHQEUIj0BNEkUKZgVKQLzErYSErYSErYSErYSAAAAAgAvAG4B7AItAFwAbAAAEjIWHQEUFjsBMjY9ATQ2FhcVFBY7ATIWFAYrASIGHQEUFjsBMhYUBisBIgYdAQ4BIiY9ATQmKwEiBh0BFAYiJj0BNCYrASImNjsBMjY9ATQmKwEiJjY7ATI2PQE0FyIGHQEUFjsBMjY9ATQmI6kRDAwGagYLFRQBCgZMCQkJCUwGCgoGTAkJCQlMBgoBDBEMDAZpBgwMEQwLBkwLCgoLTAYLCwZMCwoKC0wGCzsGDAwGagYLCwYCLAkJTAYLCwZMDAkJDEwGCwwRDAsHawYKDBEMCwZMCQkJCUwGCwsGTAkJCQlMBgsUFQoGawcLFRQLBkwJjwsGagcLCwdqBgsAAAAFACj/2wIBA0AAPwBHAE4AUgBZAAATMh0BMzU0MzIdAR4BFRQGIiY1NCYnER8BHgEVFAYHFRQiPQEjFRQiPQEuATU0NjMyFhUUFhcRJy4BNTQ2NzU0FwcRFxEiJiMHDgEVFB8CETMRFxE+ATU0J9sUQxUUQlQMEQw9MEEWIi1gRilDKUNVCwgJDT4xSSYvW0M2DUMCCAJgM0U7PSlDKTZKPANAEhcXEhIeEW5GCQoKCTVUEf6VJg4UUy1GaAUSEhISEhISGBFuRwoKCwk1VREBcCsWUzBFZQgYElIB/ssmAVsBAgdNNEcqI0j+oAE6GP7fBU42RisAAAUAKwAFAnADDQAHABYAHgAmAC4AABIyFhQGIiY0JDIWFRQHAQYjIiY1NDcBBCIGFBYyNjQSMhYUBiImNDYiBhQWMjY0dmhLS2hLAe8UDgL+UQUKCQ4CAa/+uEgyMkgyvGpKSmpKo0gyMkgyAw1LaEtLaEsMCAUE/SgIDAgFBALYITJIMjJI/lFLaEtLaCIySDIySAADACj//wIMAxkAKQA1AEIAABM0NjMyFhUUDwETNjU0JyY1NDMyFhUUBxcWFRQGIi8BBiMiJjQ/AScuATciBhUUHwE3NjU0JgMHDgQVFBYzMjdcY0hHYEdptww2Dw8aSBw3Aw8RBS5Eal6EQlpHDBWqN0kSTms0Sl80ARQXGBBqTF42AnBGY2lEUjNK/vkcIEUzDw4QZEE2L04FBQgNB0NLe7A9QWYNN55NMyQeb0sqOzNO/pYlAQ4WIC8bR2NGAAABADQCGQBdAvMACAAAEzIdARQiPQE0SRQpAvMSthISthIAAAABADT/rAEIA2UAGgAAEzQ+AzMyFRQHDgEdARQWFxYVFCMiJy4BNTQiMTgsDBARSFFcPREQBwpUXgH0Rn9SPhwQEAsruF/ZdqwlChEQBTDLcgAAAAAB/9P/rACnA2UAGwAAExQOAyMiNTQ3PgE9ATQmJyY1NDMyHgMVpiIxOSwLEBFGU1RFERAMLDgyIQEfR39TPhsQEQoqtWjZZbQpCxAQHD5TfkYAAAAFAC4BYgHCAvcAJwA3AEcAVwBmAAATNDYyFh0BFBY7ATIWFAYrASIGHQEUBiImPQE0JisBIiY0NjsBMjY1JyY1NDYzMh8BFhUUBiMiJzc2MzIWFRQPAQYjIiY1NDcHNjMyFhcUDwEGIyImNTQ3PgEyHwEWFRQGIyIvASY14wwRDAcEmQgJCQiZBAcMEQwHA5kJCQkJmQMHfAUOCQYFOgYMCQkFygUHCQ0FOQYJCQsFkAYICAwBBjoFBgkOBcULEgY5BQ0JBwU6BQLkCQkJCZkDBwwRDAcDmQkJCQmZAwcMEQwHA1UFBwgOBToFCQkLBVcFDggHBToFCwkJBZAGCwkJBjoFDggHBTQLBToFBwgOBToFCQABAC8AXgHAAe4AIwAAEzQ2Fh0BFBY7ATIWBisBIgYdARQGJj0BNCYrASImNjsBMjY14xUUBwSZCwkJC5kEBxQVBwOZCwoKC5kDBwHeCwkJC5kEBhUVBgSZCwkJC5kEBhUVBgQAAv/9/5wAjwBQABQAHQAAFzI+ATU0LgE1NDYyFhUUBiMiJjQ+ASIGFRQzMjY0EBAeEBUVHi0gSzQJCQlXCwYMBQg7DA0EAwkYFBcfHxc0Sg0QDGIIBQwHCgAAAAABAC8BEQHAATsACQAAEyEyFgYjISImNkABcAsJCQv+kAsKCgE7FRUVFQAAAAIALv/lAJkAUAAJABEAADcyFhQGIiY1NDYXFDMyNTQjImQWHx8sIB8KDQwMDVAeLh8fFxYfNQ0NDAAAAAEALgAOAgYDDQAPAAABNjMyFhUUBwEGIyImNTQ3Ad8FCgkOA/5SBQkJDwIDBAgMCAUE/SgIDAgFBAAAAAMANAACAcwDGQAUACEAMAAAEjIWFREOASImJzQmNTQ2NRE0JjU0JCIGFREeATMyNjURNAcyFhUUDwEGIiY1ND8BNquqdwR2pHYDAQEBARCIXgJeQkRfOAgOBdYEEA4G1gUDGXZV/nZRcXJSAgQCAQMBAXYBAwFVTV5E/nlBW19EAYBDkg4JBwXHBA4IBwbGBQAAAAABACgAAwEbAxwAJQAAEyImNTQ2MzIWFREzMhYdARQGKwEiJj0BNDY7AREOARUUHgEVFAZcDiZKNQsJVQQHBwTSBAcHBFQcJQ8PCwI8OyY1SggM/SQGBBUEBgYEFQQGAsUHLx4VHhEHCA4AAAABACgAAQHAAxgANgAAEjIWFRQOBg8CBgcGFRQWMyEyHQEUIyEiJjU0PgU/ATY1NCYjIgYHFAYiJjU0nqp3BAgIDAkMBwUEG6tQEjIlAQ0KCv7yNEsECggRBxMB/C9fRENeAQwRDAMYdlUPHhgWEw4OBwQEGZVQFSEkMgoVCks0DRgVDxIIEQHlL0RDX15ECQoKCVUAAQAo//8BvwMYAEgAABMUHwEUBiMiJyY1NDYzMhYXFQYHBgcGFRQfARYXFQ4BIyImNTQ3NjMyFhUHBhUUFjMyNj0BNC8BJjU0Nz4CPwE2PQE0JiMiBlEHBw8JCwQQd1VRdQUFIg8tDg08IwUFdVFVdxAECwkPBwdfRENfEz8fHAcOEQUVFV9DRF8CTBcXFwgNCyYpVXdwUBUxIRAsERkYEDsgMxZQcHdVKSYLDQgXFxdDYF9EAR8WPx8sKx4GDhEFFhgfAURfXwACACj//gHaAxkAIQAwAAAAMhYVAzMyHQEUKwERFAYrASImNREjIiY1ND4FPwEXIgcjDgEHBhUUFjsBESYBMi4fAVIKClIGBBUEBq41SgUKCRAIEgG4JgQDAQHEGRIyJa0CAxkfFv6yChUK/pwEBwcEAWRLNA4YFg8SCA8BqRoDAbIZFSAkMgFQCgAAAAEANP//AcsDFAA1AAATMzIVFCsBIgYXFRQVHAEVFBY7ATIWFAYiJjU0NzYzMhYVFAcGFRQWMzI2NTQmKwEuAT0BNDaw7BIS7CAzATUbUlV2dqp3EAQMCQ4BDV9EQ19eRE4xTEkDFBQVMx4CCA4CYDgdNXaqd3dVKSYLDAgEAx8gQ2BfRENfAUYtuTBJAAAAAAIANAAAAc0DFwALADEAAAEiBgcVFBYzMjY0JjcVFAYiJjU0JiIGHQEUFzI/AT4BMzIWFAYjIiY1NDYxETQ2MzIWAQBCXwFfQ0RfX4gNEAxfh18DAgIIE1AwVXd3VVR4AXZVUXsBblxCBUNfX4df6AoICgoIQ19eRPMKAQIIFyh2qnd2VAICAX5VdnUAAQAu//8CEwMXAC8AAAEUBg8BAzMyFCsBAwYdARQGKwEiJj0BNDc2PwEjIjU0OwETNjU0IyEiPQE0MyEyFgITBQICmS8SEkehEwYEFQQGCglQSikSEkGoAQz+WgoKAacWHgLhCQ4EA/7/Kf7wIRVJBAcHBEkYGRKGfRQVARoBBA0KFQogAAAAAAMAKP/+Ae0DIQAdACUALQAABCImNTQ2NzY0Jy4BNTQ2MhYVFAYHBhQXHgMVFAQyNjQmIgYUEjI2NCYiBhQBaLyETSYEBCFShLyFUyAEBAohKh7+0Zhra5hqaphra5hqAntYQ2YPAQoCDWNIWHt7WEdkDQIKAQQZLEcoWFJkjGRjjgEaZIxkY44AAAAAAgAr//4BxAMdACAANwAAAR4BFRQHAwcGIyIvASY1NDcTNiYPAQYjIiY1NDc+ATMyFyYjIgYHBhUUFhcWMzI2NzI2MTY1NCYBbCotJdxxAgcEAhEEAvwHCwgXCAhacyUdWTFAHSkzJ0cYHiQhKjQmRRcBAh0kAvcdWjFANP7JogQCCwMGBAIBZgoCAwMBe1JANCktRh0kISozJ0YYHiIgBCkzKEcAAAAABAAq//8AlQHKAAkAEQAbACMAABMyFhQGIiY1NDYXIhUUMzI1NAMyFhQGIiY1NDYXIhUUMzI1NGAWHx8sIB8XDQ0MDBYfHywgHxcNDQwByh4uHx8XFh8pDA0NDP7JHi4fHxcWHykMDQ0MAAAABP/9/7wAjwHPAAcAEAAoADAAABIyFhQGIiY0FyIGFBYyNjU0AzI+ATU0LgE1NDYyFh0BDgEjJjU0NjMyNyIGFBYzMjRDLR8fLR82BgcHCwdVER4PFhUfLR8DSTMSCQkBSQYHBwYMAc8eLh8gLAoHCggIBQz+Pw0NAgILGRMWHx4XAzNIAhIIDWEHCgcYAAAAAQAo//8BtQMNABwAAAEyFhUUBwEGFRQeAR8BARYVFAYjIicBJjU0NwE2AZ0JDgX+uRcJBwkIAT0GDwgHBf6zHSMBRwUDDQ8IBwX+yhcXCxQJCAf+0wUHCA8FAT0dKC4dATcFAAIALwC4AcABmAAJABMAABMhMhYGIyEiJjYXIR4BBiMhIiY2QAFwCwkJC/6QCwoKCwFwCwkJC/6QCwoKAZgVFBQVtgEUFRUUAAEALv//AboDDQAcAAATMhcBFhUUBwEGIyImNTQ3ATI+AjU0JwEmNTQ2RQUFAUgiIf63BQYIDgUBPQEQBwgW/rkFDgMNBf7JHC8pIf7IBQ8IBwUBLQ4JFQsYFgE2BQcIDwAAAAADACj/5AG/AxgAKAAyADoAABMUFjEUBiMiJyY1NDYyFhUUBgcGBwYXFRQiPQE0PgM3PgE1NCYiBhIyFhUUBiMiJjQXIhUUMzI1NFEODwgLBRB3qnZGNhYKGgEpERUcDAQsN16IX40uHh8WFx82DQ0MAk0XLwgNCyYqVXZ2VT9mFwsKGiKTEhKSGSoZFQUCE1AzQ19f/b8fFhcfICwKDA0NDAAAAAIAKAAAAm8DFgBOAFgAACUUDgMjIiYQNjMyHgEXFBYdARQGIyInDgEjIiY0NjMyFzc+AjMyFhUUDgEHFAYVFBYVFAYVFBYyNjU0LgEjIgYQFjMyPgI3NjMyFic0JiMiBhQWMjYCQBUrN1IreaureVCDSAcBOSkrHBJDKTpSUjpDKgECAwgFCQ8EBgIBAgEiLiI4dkxok5NoK00zGwkEDwgKlT8kKTk6UDq9CSo3MSLoAUboap9ZBA4DCik5HiozYoxhPgQEBAUMBwIKHRcEDAMEDAQCBAIXISIXTZpx0P7c0CY7KBMKCtE/PERiRUEAAAIANAAAAnsDFwAVABsAAAEyFhURFCsBIjURIREUKwEiJjURPgEWIgYHISYBWHmqChUK/gsKFAQHBqfcypIDAfQDAxfno/59CgoBZP6cCgYEAYOl5SnIj48AAAAAAwA0AAECfQMZAB8ALwBAAAATNjMwFzM3HgEVFA4BDwEGFhcWFxYVFAYjIS4BJxE0NhciBh0BFBYzITI/ATY0JiMDIgYdAR4BMzIzITI2NTQmJ68JDDxsAVN1Ex8GHQMDBEUjMXdV/v4ySAFIOCQzDAkBFRMRMTBfRPcJDAEwIAEBAQhBW1U+AxgBAQEBeFMYMTUPHQMNARcqOUtVdwJGMgIeNEknMiTtBw4RMjCGX/5/DwjbIjBhQj9cBgABACgAAQIhAxgAHwAAASYjIgYQFjMyNzYzMhYVFAcGIyImNTQ2MzIXFhQGIyIB/UtmaJOUZ2hJBwoICwdUenmrq3l6VAYMBwoCh2jQ/tzRaAoLCQkKdOiko+h0CBIMAAACADQAAAIYAxYADwAdAAATMx4BFRQGByMuAScTIzQ2FyIGFREeARczMjYQJiOsU3WkqXhKMkYBAQFFOyQzATAhRWiTk2gDFgbmn6PmAghCMAIdM0glMiT94yEuAtABJNAAAAAAAQA0AAIBywMZACoAABMhMh0BFCMhIgYdARQWOwEyHQEUKwEGHQEeATMhMhYdARQGIyEiJicRNDazAQ0KCv7zJDIJBdgKCtgOAjIjAQwEBwcE/vM0SQJLAxkKFQozJPMECQoVCgQL5CMvBgQVBAZHMwIdNUsAAAAAAQA0AAABywMXAC8AABMhMhYdARQGIyEiJxUiBh0BFBY7ATIWHQEUBisBBhURFCsBIiY1ETQxNyM0NjMVNrgBCAQHBwT++AMBJDMKBdcEBwcE1w8KFAQHAQFLNQEDFwYEFQQGAQEyJPMECgYEFAQHBAv+qwoGBAKLAQI0SwEBAAABACgAAAJeAxcAMQAAJTI2NzU2NTY1NCYnISImPQE0MyEeARUUDwIOASMiJjU0NjMyFxYUBiMiJyYjIgYQFgFMSH0hAQIvIv79BAYKAQUyRgIDASWTVHmrq3lzWwcNCAkGS2Zok5Qpb2oCAgEMBSMyAQcEFAoCSjMRCAwBdX3opKPodAkQCwdo0P7c0QAAAAABADQAAAJ1AxgALAAAEzMyFhURFBYzITI2NRE0NjsBMhYVERQrASImNRE0JiMhIgYVERQrASI1ETQ2PhUEBgkHAdAFCgcEFAMHChQEBwkG/jAGCgoVCgYDGAgD/psGCwoHAWUEBwgD/P0KBgQBVQYJCgX+qwoKAwMEBwAAAQAuAAABFQMXAB8AABMzMhYdARQGKwERMzIWHQEUBisBIj0BNDsBESMiPQE0ONIEBwcEVFQEBwcE0goKVVUKAxcGBBUEBv07BgQVBAYKFQoCxQoVCgAAAAEAKAABAh8DGAAnAAATITIWHQEUBisBEQ4BIyImJzU0NjsBMhYdAR4BMzI2NREjIiY9ATQ2+QEbBAcHBFQCd1NUdwEHBBQEBgFfQ0RfngQHBwMYBgQVBAb92FJ0dlQGBAcHBAZDXmBDAiIGBBUEBgABADT//wIzAxkAMQAAATIWFRQPAwYUHwEBFhUUBiMiLwImKwEiBhURFCsBIjURNDY7ATIXERQ7ATI3ATYCGgkPA4jPCwgIDAFWAxEIBQOH3QgJMAYJChUKBgQVBQUPGwwIAXYDAxkQCAUDh9AKCQUIC/6pAwQJEAOI3AgKBf6qCgoDAwQHC/6cEQgBdgMAAAABADQAAAHKAxgAHgAAEzMyFh8BER4BFyEyFh0BFA4BBwYjIiYrASImJxE0Nj8UAgUCAQIxIQEOBAcEBgEBHhJdEmsySwMHAxgFAwL9bCEuAQYEFQIEAwEBAUUyApYEBgABADQAAAJ5AxgAMwAAATI+ATU3PgEzMhYVERQrASI1ETQjIgYPAQ4BIiYvASYnJhURFCsBIjURNDsBMhYfAh4BAVcYKBBPCEQtBAYKFQoDCR8ITgo+YEMJSw0gBgoVCgkBLEQJTAQIKAGIGhkG/SI4CAP8/QoKAtkDHRb/HTg5JvUjEAMG/ScKCgMDCzYk9gsTIgAAAQA0AAEBzQMZACgAABMyFhcTFhcWMjY1ETQ2OwEyFhURFAYjIiYnAy4BJyYVERQrASI1ETQ2PjFCB7kOGQMFBAYEFQQGBgQqRAy5CBMSBgoVCgYDGT0d/ackDQIDAwLVBAcHBPz9AwczJwJZFhQJAwb9JwoKAwMDCAAAAAIAKAABAm8DGAAIABEAABIyFhAGIiY1NCUiBhAWMjYQJtPyqqryqwEkaJOUzpOTAxjn/rjo6KSjv9D+3NHRASTQAAAAAgA0AAABywMXABUAJQAAEzMeAR0BDgErASIGFREUKwEiNRE0NhciBh0BFBY7ATI2PQE0JiOwVFN0AXdUlgUHChUKSDYjMgcFlkNgYEMDFwJ2UxJUeAgE/qgKCgKONEknMyP0BQhgQxJDXwAAAgAo//8CcAMWACAAQAAABSIuAyMiDgIjIiY1NDYyFhUUDgMVFBYzMhYUBicyFhUXFRQxMj4BNTQmIyIGEBYzMjc2PQE0JiMiJjQ2AlwXJhcRCAEDHSQ+IHmrq/KqFB0dFC0iCQsL3jZEAQUfIJNnaJOUZ05AAzIkCgsLAQ0SEw0UFxTopKPo56Q3ZUIxGgINKwwRDPxIFQEBATp3P5LQ0P7c0UADCAkkMgwRDAAAAAACADQAAQHMAxkAMQBAAAATNDYzOgE7AR4BHQEOASsBFhcBFhUUBiMiJwEuBCc0JjUnNDU0IyIGFREUKwEiNRMiBh0BFDsBMjY9ATQmIzRPMQEPBjpTcwF2VGoDFgEaAxAJBAP+5gkNBgMDAQEBAwUHChUKfiMyDJZDX19DApk4RwJ1UxNUdx8W/uYDBAkQAwEaChEQCQ8DAQQBAQEBAwkE/qgKCgLkMyP0DF9DEkNfAAEAKAAAAgIDGQA2AAAlMjY1NCclLgE1NDY7AR4BFRQGIiY1NCYrAQciBhUUFwUXHgIVFAYjNSMiJjU0NjMyFhUUFjMBTztSPf7eJi9oSldRbwwRDF9DKiI6UjwBEhYNHyRqSlRVdwsICQ1fRCpQOUUsqRZTMEppBXVSCQoKCURfAVA5RiufDggdRyhKagF3VQoKCwlDYAAAAQAuAAIBxQMbAB0AABMhMhYdARQGKwEiBhURFAYrASImNRE0JisBIj0BNDgBggQHBwSWCQ0GBBUEBg0JlwoDGwYEFQQGDwj9MgQHBwQCzggPChUKAAAAAAEANAAAAnsDFwAbAAABETQ2OwEyFREOASMiJjURNDY7ATIVERceATI2AlIHBBQKBqZ3easHBBQKAQOSypIBfwGOBAYK/n2l5eejAYMEBgr+nCqPx8cAAAABAC7//QJ8AxsAIAAAATIWFRQVAw4BIyImJwMmNTQ2MzIXEx4BMzI+AzcTNgJlBw/MCDUiITQIxAENCQ4EwQQiEw0WCwgCAcsEAxoLCQMC/UchKiUdAsMDAggLDf1JFhoLDRIHAgK0DQAAAAABADQAAAJ8AxsANwAAJQ4CKwEuATURNDY7ATIWFREeATsBPgE1ETQ7ATIVERQWFzMyNjURNDY7ATIWFREOAgcjIi4BAVgPLhwJJkFbBgQVBAYCSDIYIjAKFQowIhkzSQYEFQQGATlEHyQKHC46FxwHBF9CAmsEBwcE/ZEyRgIyIgEQCgr+8CMyAUkzAmsEBwcE/ZY2TyABBh0AAAABAC7//gHXAxgAMwAAEzIXExYyNxM2MzIWFRQHAwcGFRQXExYVFAYjIicDJyYiBwMGIyImNTQ3EzY1NCcDJjU0NkYMBKICEQKhBQoJDwKhDQYHrgIPCAsFlgwCEgKiBQoJDwKuBwauAg4DFwn+wAQEAUAJDAkDBP7BGAoNDwz+qQQECAwJASkWBQX+wQkMCAQEAVcMDw0KAVcEBAgMAAAAAQAy//8CegMYADEAAAE0NTA1NDsBMhYdARQGBw4BFREWBisBIiY1ETQmJy4BPQI0NjsBMhYdARceAjI+AQJQChUEBpBqCQwBBwQVAwcNCGuPBwMVBAYBAkRxhXJDAr8MHiMLBwRBlN0WAg4H/t0EBwcEASMHDgIV3ZQBQQQHBwQjKl2eW1ueAAEALP/+Ad8DFAA2AAATIR4BFRQHFQcDMzIVFCsBAw8BBhUUMyEyFh0BFAYjIS4BNTQ3EyMiNDsBEzc1NzY1NCMhIjU0RQFmFh4HAqMvEhJHwwEBAQ0BbAQHBwT+kRYdCbY/EhJXrgMBAQz+mw0DFAIeFRALAQL+7BQV/rYBAQEECwcEFQQGAh4VEQ0BMykBJwQBAQEEDBUUAAAAAAEANP+DANwDlwAZAAATMhUUKwEiBgcRFBY7ATIVFCsBLgE1ETQ2N8oSEhciMwEyJBcSEho0SEkzA5cUFTEg/OUkMhQVAkk0AxsyRgIAAAAAAQAuAA4CBgMNAA8AABMmNTQ2MzIXARYVFAYjIicxAw8JCgUBrwIPCQkFAu8EBQgMCP0oBAUIDAgAAAAAAf+6/4MAYQOXABkAAAMeARURFAYHIyI1NDsBMjY1ES4BKwEiNTQzGzNJSDQaEREXJDIBMyIXEREDlwJGMvzlNEkCFRQyJAMbIDEVFAAAAAABAC0BeQHEAxIAIQAAEyImMScmNTQ3EzYzMhcTFhUUDwEGJicDLgE1LgEHAwYjIkcBARMFAbgGDQ4FtwEFEwMKAZ0BAQMDBKIDBwEBegEJAgcDAgF3CQn+iQIDBwIJAQMDAUABAwEIAQX+twYAAAAAAQAp/+YBsAACAAoAACQUKwIiJjY7AgGwDLi4CAYGCLi4AhwODgAAAAEALgIZAFcC8wAIAAATMh0BFCI9ATRDFCkC8xK2EhK2EgAAAAIAKAAAAcABmAAbACMAABMyFhc1NDY7ATIWFREUBisBIiY9AQ4BIyImNDYWIgYUFjI2NPQxVhwGBBUEBgYEFQQGHFYxVXd3mYhfX4hfAZgsJUYEBwcE/n4EBwcERiUsd6p3KV+IX1+IAAAAAAIANAABAcwDFgAfACsAABMzMhYVETYzMhYUBiMiJxUUBisBIiY9ATQmNDY1ETQ2EyIGBxUeATMyNjQmPxUEBjxmVXd3VWU9BgQVBAYBAQbFQF0FBV1ARF9fAxYHBP49UHaqd1FFBAcHBLUBCAQHAQI0BAf+WVdAFkBYYIZfAAAAAQAoAAABewGYACEAABMyFhUUDwEGIyIuASMiBhQWMzI2NzYfARYVFA4BIyImNDb0LVkDDgMDBh0wHERfX0QdPAwICA4EJUEhVXd3AZgpDgUDDQISE1+IXxgMBgYNBAMIGhd3qncAAAACACgAAQG/AxYAGwAoAAABMhYVERQGKwEiJj0BDgEjIiY0NjMyFhcRNDYzAyIGFRQWMzI2NzUuAQG1BAYGBBUEBhxWMVV2dlUxVhwGBK1DX19DQF4FBV4DFgcE/QIEBwcERSUsd6p2KyUBwwQH/llfQ0RfWEAWQFcAAAAAAQAoAAIBvwGZACsAABMyFh0BFCMhIiY9ATQ2OwEuASMiBhQWOwE2NzYzMh8BFhUUBw4BByMiJjQ29FR3Cf7sBAcHBPIJWzxEX19EGEAtDwgCAhIFERJKMBpVd3cBmXdUCQgGBBUEBjtPYIZfBi0UAQkDBQcVFCsDdqp3AAEALgABAiwDGQAvAAABMhYXFRQGKwEiJj0BLgEjIgYdATMyFh0BFAYrAREUBisBIiY1ESMiPQE0OwE1PgEBYVR2AQYEFQQGAV5DRF/8BAcHBPwGBBUEBl0KCl0CdwMZdVQGBAcHBAZDXV9DtgYEFQQG/p0EBwcEAWMKFQq8UnMAAgAo/oIBwAGZACgANAAAEzIXNTQ2OwEyFhURBw4BIyImJzU0NjsBMhYdAR4BMzI2NREGIyImNDYXIgYUFjMyNjc1LgH0ZT0HBBQEBwECdlNUdwEGBBUEBgFfQ0RePWVVd3dVRF9fREBdBQVdAZlRRQQHBwT9wAZSc3VUBgQHBwQGQ11fQwEFUXeqdylghmBYQBZAWAAAAAABADT//wHMAxMAKgAAEzMyFhURNjMyFhcVFAYrASImPQEuASMiBgcVFAYrASImPQE0JjQ2NRE0Nj8VBAY9ZVR3AQYEFQQGAV9DQF0FBgQVBAYBAQYDEwcE/j1Rd1TBBAcHBMFDX1hAywQHBwS2AQcECAECMwQHAAACAC4AAQEWAiQADwA7AAATMzIWBxUWBicjIiY9ATQ2BzMyFhURFBY7ATIWHQEUBisCIjEjIiY9ATQ2OwEyNicRNCYrASImPQE0NooeBQoBAQoFHgUJCTBXBAcKBUUEBwgDXxQBXgQHBwREBwoBCAYqAwgHAiQKBR0FCwEKBR0FCosHBP6rBQkHBBQEBwcEFAQHCAYBKQUJBgQVAwcAAAAAAv8f/oIAtwIjAA8ANgAAEzMyFgcVFgYrASImPQE0NgMiJjU0NjsBMhYdAR4BMzI2NRE0JisBIiY9ATQ2OwEyFxYVEQ4Cix0FCgEBCgUdBgkJmlF7BwMVBAYBX0NDXwgGKgMIBwRXCAECAj9ZAiMLBB0FCwsFHQUK/F9zXQQHBwQGQ11fQwITBggHAxUEBggIu/6BP2AtAAABADT//gHKAxgAMwAAEzMyFhURFBUUMzI/ATYyHwEWDwEGFRQXBRYVFA8BBisBIi8BJSYjIhcVFAYrASImNRE0Nj4VBAYFAhXkAwoCDggJ5xIMAToEAgcEBA8BBAL+0QsFCAEGBBUEBgYDGAcE/lYDAhETzQIDDwgH0BAKCQn2AwYEAggGAgLtChLcBAcHBAMBBAcAAQAuAAABFQMZAB4AACEjIiY1ES4BKwEiJj0BNDsBMhYVER4BOwEyFh0BFAYBCgE0SQIvIQIDBwoBNEgCMCECAwgHSzUCHiIwBgQVCko1/eEhMQYEFQQGAAEAPP/+AoEBlgA7AAATMzIWFQc2MzIXFjMyPgI3MzIWFxUUKwEiJj0BNCYjIgYVERQGKwEiJj0BNCYjIgYVERQrASImNRE0NkcVBAYBLDllKQICBBIXMB4GTFcBChUEBkk4KDwGBBQEB0g4KTwJFQQHBwGWBwQgKTwDExcUAVBQ6wsHBOs+OTYn/vsEBwcE6z45Nif++wsHBAGCBAcAAAABADQAAAHLAZcAHwAAEzMyHQE+ATMyFhcVFCsBIj0BLgEjIgYHFRQrASI1ETQ+FQocVjFUdgEKFQoBXkNAXgUKFQoBlwpHJSt2VMIKCsJDXldAzAoKAYMKAAAAAAIAKAABAb8BmAAHABEAABIyFhQGIiY0JCIGFBYzMjY1NJ+qdnaqdwEQiF9fRENfAZh2qnd3qk1fhmBfREMAAAACADT+gwHLAZgAHwArAAATIiY1ETQmNDY9ATQ2OwEyFh0BNjMyFhQGIyInERQGIxMyNjQmIyIGBxUeAT8EBgEBBgQVBAY9ZVV2dlVmPAYErEReX0NAXQUFXf6DBwQCNAEHBAgBtQQHBwRFUXeqdlD+PQQHAadeiF9YQBZAVwAAAAIAKP6BAncBmAAkADAAABMyFzU0OwEyHQEUFhQGFREUFjMyMzIWFRQGIyImJxEGIyImNDYXIgYUFjMyNjc1LgH0ZjwKFQoBAV5DAQEJCwoKVHcBPGZVd3dVRF9fREBdBQVdAZhQRQoKtgEHBAgB/otDYA0JCAt2VAEGUHeqdilfhmBXQBdAVwABADQAAgGsAZoAKQAAATIeAxUUBiMiJy4BIyIGBxUUBisBIiY9ATQmNDY9ATQ2OwEyFh0BNgEAHzonHg0QCQgEFUcqQF0FBgQVBAYBAQYEFQQGPAGYEhkcFQUIDQYgJ1dAywQHBwS1AQgEBwG4BAcHBEdQAAEALQAAAXEBmAAvAAABNCYjIgYVFBYXFh8BHgEVFAYiJjU0MzIWFRQWMzI2NTQnJi8BJjU0NjIWFRQjIiYBSUkxMkc5TRUMETAzX4ZfFAgNRzIxSDQWSRR0X4ZfEwgNASsdJygcHxwSBQMEDjcgLUBALQ4HBxwoJx0kEwgRBSFILUBALQ4HAAABAC4AAgHGAlYALQAAEzMyFh0BMzIWHQEUBisBFRQWFRQWMzIzMhYVFAYjIiYnNSMiJj0BNDY7ATU0Nu8VBAatBAcHBK0BXkIBAQkLCgpUdwGsBAcHBKwGAlYHBIcGBBUEBr0CCwNDYA0JCAt1VNAGBBUEBocEBwABADQAAAHLAZgAJQAAISMiJj0BDgEjIiYnNTQ2OwEyFh0BHgEzMjY3NTQ2OwEyFhURFAYBwRUEBhxWMVR2AQYEFQQGAV5DQF4FBgQVBAYGBwRHJSt2VMEEBwcEwUNeV0DLBAcHBP5+BAcAAAABAC3//gH4AZsAGwAAEyY1NDYzMhcTMB4BMzI3EzYzMhYVFAcDBiMiJy8CDwkKBbMDBAQGBbMFCgkPArENJSMOAX4EBAgNCv6eBQMIAWIJDAgEBP6hISEAAQA0//8CfAGZADUAACUOASsBLgE9ATQ2OwEyFh0BHgE7AT4BPQE0OwEyHQEUFhczMjY1Jz0BNDY7ATIWHQEUBgcjJgFYFzkSJkFbBgQUBAcCRzIZIjAKFQowIhkzSQEHBBQEB2U4Jj45IRkEX0LnBAcHBOsyRgIyIkcKCkciMgJJMwEB6QQGBgTsR1sCAwAAAQAuAAABxQGYAFkAAAEzMhYxHwEWFTAWFRQGFCIxDwEGHwEWHQEUFjEUByMPATAGKwEwJiImIycmDwEGIwYrASIvAiY9AjQ/ATYvASY9ATQyNT8BMjYxMzIWMTIfARY/ATQ7ATYBqQUBAgEPAgEBAQGmBQWmAgECAQ8BAgEDAwEBAacEB6UBAQQCAwIBAQ8CAqYFBaYCAQEQAQIDAQMCAqUFBqYBAgEBmAEBDwIBBAEBAgICpwUFpwIBBAECAgIQAQEBAagEBKcBAgECDwIBAgYBAqcFBacCAQgBAQIQAQECpgQEpgIBAAEANP6CAcwBmwA2AAATMzIWHQEUFhUUFjMyNjc1NDY7ATIWFREHDgEjIiYnNTQ2OwEyFh0BHgEzMjY1EQYjIiY9ATQ2PhUEBgFfQ0BdBQcEFAQHAQJ2U1R3AQYEFQQGAV9DRF49ZVV3BgGbBwS7AQYBRF9YQMsEBwcE/cAGUnN1VAYEBwcEBkNdX0MBBVF3VcMEBwABAC4AAgHFAZkAOwAAJSEiPQE0PwE2JisBIiY9ATQ2OwEyPwI2JiMhIj0BNDMhMh0BFA8BBhY7ATIdARQrASIPAQYzITIdARQBu/59CgSVAQIBLAQHBwRWBgl0CQICBP7BCgoBgwoDjwECASIKCkwGBooGBwFFCgIKFQQEkAEDBgQVBAYJcAgCBwoVCgoVBAOKAQIKFQoGhgYKFQoAAAAAAQAt/4EBYQOVAC8AADM1NCYjIiY0NjMyNjcRNDY3MzIVFCsBIgYHERQGIyIUMzIWFxEUFjsBMhUUKwEuAbkyJBcfHxcjMQJJMxoSEhciMwFLNA0NMkwBMiQXEhIaNEj8JDMfLB8xIwEKMkYCFBUyIP73MksYSC/++yQyFRQCSQABADz/6gBlAywACAAAEzIVERQiNRE0UBUpAywS/OISEgMeEgAB/7j/gQDsA5cANgAAAzQ2MzIWMx4BFREeATsBMhYUBisBIgYdARQGByMiNTQ7ATI2NRE+ATsBMjQrASImNREuASsBIkgTBgQNAjNJAjEjARceHhcBJDJINBoSEhckMgFMMgEMDAE0SwEzIhcSA4EGEAICRjL+9iMxHywfMyT8NEkCFBUyJAEFL0gYSzIBCSAyAAAAAQAyAbUBiwJLACsAABMiNTQ2MzIXHgIXMzI2NTQmNTQ2MzIXFhUUBiMiJy4CJyMiBhUUFhUUBkcVPCgqHwgRFhUFGCEEEAkMAwY9KC0cBxEXFQUXIgQPAb0sKjgjCSkWAiIXBg8BCAoJEBEpNyIJKBcCIhcIDgEIDAAAAAMAMAAAAJsDNQAHABEAGQAANxQiNRE0MhU2IiY0NjMyFhUUJzI1NCMiFRR6KSkCLCAfFxYfNQwMDRISEgJbEhJdICwfHxYXCg0MDA0AAAAAAgAwAAMBggIZACoAMAAAEzIdAR4BFRQPAQYvASYnET4CMzIfARYVFAYHFRQjIj0BLgE9ATQ2NzU0FQ4BFBYX+RQnTgMOCQoMHCkdKRMEAwQOA0wpFBVMaGhMPE9PPAIZEikEJg8DAw0ICgkSBf69BBIPAw0DAw8lBDMSEjMJc04BTnMJKhJmCFt6XAgAAAAAAgBC/+gAawMqAAcADwAAEzQyFREUIjURNDIVERQiNUIpKSkpAVQSEv6mEhIDHhIS/sESEgAAAAACADz+gAHUAxcAOQBGAAATPgEzMhYXFRQGKwEiJj0BLgEjIgYVETYzMhYVFAYVEQ4BIyImJzU0NjsBMhYdAR4BMjY1EQYjIiY1ITQmIgYHFRQWMzI2NzwDe05UdwEGBBUEBgFfQ0RfPWZXdQEEe0xUdwEGBBUEBgFfhl89ZVh0AW5fhl8BYENFXAECTF5tdVQGBAcHBAZDXV9D/vtQe1ACCAH+i2BsdlQGBAcHBAZDXl9EAQVRfFBEXl9CAURfYUEAAAAAAwAwAMcCfQMUAAcADwA0AAASMhYUBiImNCQiBhQWMjY0JzIWFRQPAQYjIi4BIyIGFRQWMzI+ATMyHwEWFRQGIyImPQE0Nt30rKz0rQGQ0pWV0pT+LFsDDwMDBRswH0RfX0QfMBsFAwMPAlcvVXd3AxSs9K2t9IOU0pWV0mIoEQMDDQISE19DRF8TEgINAgQQKXZVAVV2AAAEADwAxwKJAxQABwAPACwAOQAAEjIWFAYiJjQkIgYUFjI2NCUzMhYUBiMiJyYVFxYVFAYjIi8BFRQrASI1ETQ2FyMiBh0BHgEzMjY0Jun0rKz0rQGQ0pWV0pT+xUw1Sko1HxwFsAUPCAcFqAoVCh9gTAQGAjIiJDIyAxSs9K2t9IOU0pWV0n1KakoOAgO0BwUIDgWtowoKAYYUHikHBFAiLzJIMgAAAAACACoCFgEoAxUABwAPAAASMhYUBiImNDYiBhQWMjY0dWhLSmpKo0gyMkgyAxVLakpKaiIzSDIySAAAAAABADYAVQHKAesALwAAEzQ2MhYdARQWOwEyFhQGKwEiBh0BMzIWFAYjISImNDY7ATU0JisBIiY0NjsBMjY16w0RDAYEmQgKCgiZBAajCAkJCP6QCQkJCaMGBJkICgoImQQGAdkICgoImQQHDBANBgSDDBEMDBEMgwQGDRAMBwQAAAMAMP//AccDMwAmADAAOAAABCImNTQ+ATc+ASc1NDIdARQHDgEVFBYzMjY1NCcmNTQ2MzIXFhUUAyImNDYyFhUUBicyNTQjIhUUAVGqdxI+MRcfASlTI0BfRENfDAEPCQsED8wXHx8uHh8WDAwNAXdVH0BLFAorGpMSEpNUIw9MO0NgX0QjHAMDCA4LJCxVAlIgLB8fFhcfKQ0MDA0AAAABADb//wHMAxcAIwAANxwBFRQGKwEiJj0BNDcBNjU0IyEiPQE0MyEeARUUBwEOA18EBxQEBhMBWQEM/qkKCgFYFh4I/q0BCgMEUwshBRUOBwRJJB8CRgEEDQoVCgEfFhEN/cYBEgcSAAIAPP//AdQDFwAQACIAAAUiJjURNDYyFh0BBxEWDgIDIgYVER4BMzI2NRE3NCY1NCYBCFZ2d6p3AQEUK1Y3RF8CX0JDXwEBXwF4VAGAVXd3VQQB/n4TPEUxAu9gQ/56QVxfRAF7AQECAURfAAEANgACAc0BmQAhAAAlISI9ATQ3ATYmIyEiPQE0MyEyFh0BFAcBBjMhMhYdARQGAcL+fgoEAUkCAgT+wQoKAYIEBwT+tAYHAUQEBwcCChUEBAE+AgcKFQoGBBUDBP6+BgYEFQQGAAAAAQA0AAAB6AMXACYAADMiJjU0NwE2NTQjISImPQE0NjMhHgEVFAcBBhUUFjMhMhYdARQGI2oQJQkBfwIM/pMEBwcEAW4WHgr+gwMHBgFsBAcHBBsbDw8ChwQDDAYEFQQGAR4WEBD9ewYBBQcGBBUEBwAAAAANADz+gAMEAxQAAwAHAAsADwATABcAGwAfACMAJwArAC8AMwAAEyERIRMRMxEzETMRMxEzEQEVMzUzFTM1MxUzNQUVMzUzFTM1MxUzNQURMxEzETMRMxEzETwCyP04CaYIqgXg/cOmCKoF4P3DpgiqBeD9w6YIqgXgAxT7bASO/owBdP6MAXT+jAF0/oPGxsbGxsbNxsbGxsbGy/6OAXL+jgFy/o4BcgACADABewPSA6QATQBZAAABMh4DMzI+AjczMhYXFRQrASImPQE0JiMiBhURFAYrASImPQE0JiMiBhURFAYrASImJzUjIiY9ATQ2OwE1NDsBMh0BMzIWHQE+ATMFFRQWFRQWFxE0JiMCGx8zHhULAgQSFzAeBktYAQoVBAZIOSg8BgQVBAZIOSg8BgQXVHcBjgQHBwSOChUKoA0XGCoi/tgBWkAMBwMSDRMTDRMYFAFRUOsLBwTrPjk2J/77BAcHBOs+OTYn/vsEB3VUpgYEFQQGhwoKhxQQBxYUKJMCCwNBXwMBMQcOAAAAAwA2AAABHgJTAAcADQA6AAASMhYUBiImNBY0IyIUMwczMhYVERQWOwEyFh0BFAYnIwciNDEjBiY9ATQ2OwEyNicRNCYrASImPQE0Nn8sICAsIEIMDAw4VwQHCgVFBAcIA18UAV4EBwcERAcKAQgGKgMIBwJTICwfHywiGBh5BwT+qwUJBwMVBAcBAQEBBwQVAwcIBgEpBQkGBBUEBgAAAAP/C/6BAK4CUgAHAA8APwAAEjIWFAYiJjQWIgYUFjI2NAc7AjIVMB0DBw4BIyImJzU0NjsBMhYdAR4BMzI2PQQ0JisCIiY9ATQ2YiwgICwfOgoHBwoHQ0MRAwsBAndSVHcBBgQVBAYBX0NDXwgGDhwDCAcCUiAsHx8sCgcKBwcKiQvByllcBlJ0dlQGBAcHBAZDXV9DXFnKlQUIBwQUBAcAAAAAAgA8AAECYwMZADUAVQAAEyEyFh0BFAYnISIGFRQdARQWOwEyFh0BFAYrAQ4BHQEeATsCMhYdARQGIyEiJicRNDU0NjMXMzIWHQEzMhYdARQGKwEVFBUUFjcyFgYjIiYnPQE0NsABCAMHBwP+8yMzCQXYAwcHA9gFCQIyI22fAwgIA/7zM0oCSzTSFAQHrAQHBwSsYEMLDAoNVHgBBwMZBwMVBAcBMyQBAfEECQYEFQQGAggF5CMvBwMVBAZHMwIbAQE1S8MIA7IGBBUEBpIHCURgARUUdlOl2wQHAAEALv//AngBmQBJAAATMh8FPwE2Mh8CPwQ2MzIVFDEGFQ8JBiMiLwUmIhUPBAYjIi8KNCc0MTRCEwQECBEiKj4/BR0FPz4pIxEIBAQTFAECBQgRIh4OCAMCAhARBlIXCwYDAQQDBgsXUgYSDwICBAcOHiIRCAUCAQGZCw4aNWuBe3wJCXx7gWs1Gg4LDAEDAQcNGzVqXC4XDAYHDaEsFwsFAgIFCxcsoQ0HBgwXLlxqNRsNBwEDAQwAAAAAAQA2//0CfwMaAC4AABMmNjMyFxMWMzI3Ez4BMzIWFxMWMzI3EzYzMhYHAw4BIyImJwMmIgcDDgEjIiYnNgEOCRECfQEKCwIxBB0UFR0EMQELCgJ8AxAKDgJ8Ax4UFR4CMQMUAjEDHhUUHgMDBAkMD/0mCQsBHhQZGxX+5QsJAtoPDAn9JxMbHBQBGg0N/uYUHBsTAAEAPAABAoQDGgBaAAATMzIWHQEcARUWFRYXFhceAjI+ATc2NzY3NjU8ATc1NDY7ATIWFRkBFAYrASImPQQ0JhUGBwYHBgcOASImJyYnJi8BLgEVBh0EFAYrASImNRkBNDZGFQQGAQEDBQoTRVxmW0YTCQUDAQEBBgQVAwcHAxUEBgUBBAUGCw0oa3dqKQwLBgUFAQMBBgQVAwcHAxkHAxICBgEcCiMoSUSG0XV10YZESSgjChwCDQQIAwcHA/5+/n8EBwcEvWYsFgIBAgYPFBMnI216em0jJhMVFAMBAgECFi1kvQQHBwQBgQGCAwcAAAEAAAAAAAEAAAKeAAIAAAAYAWAB/AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/fv+1/6v/q/+r/6v/sP+r/5wAAAAAAAD/q/+//7//tf+w/6v/v/+w/5wAAAAAAAD/q//Y/87/zv/O/9j/yf/O/5wAAAAAAAD/zgAAAAD/zgAA/5L/tf9RAAD/0/+DAAD/5wAAAAD/5wAA/87/0/+1AAD/5//JAAAAAAAAAAAAAAAAAAAAAAAA/78AAAAAAAAAAP/nAAAAAP/d/9P/0/+//84AAP/OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/sAAAAAAAAAAAAAAAA/87/0/+1AAAAAP+/AAD/3QAAAAD/3QAA/8T/3f+1AAD/5//OAAD/zv/nAAAAAAAAAAAAAAAA/5wAAAAAAAD/5wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/yf+DABEATAFIABAAoAEAABAAoAAQAKAAoABYAKAAWAAQABAAEAAQABAAEAAQABAAEACgAKAAEAAoAKAAEAAQABAAEABwABAAEACgAFgAEAAQABAAKACgAEAAEAAQAEAAEAAQABAAEAAQABAAEADQALgA0AAQALgAKADQAOgBAAAQABAAiADoAOgAuAC4ANAA0AC4ATAA0AEYANAAEADQAA8ATwASAAAAEgAAABQAAAAAABQAFgAUABQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAIAAgACAA4AAgAAAAQABAAAAAAABgAGAAIABgAAAAYAAgAQAAgADAAIAAoAAAAKAAAAAAAOAK4AAQAAAAAAAACwAWIAAQAAAAAAAQANAi8AAQAAAAAAAgAGAksAAQAAAAAAAwAmAqAAAQAAAAAABAAOAuUAAQAAAAAABQAQAxYAAQAAAAAABgANA0MAAwABBAkAAAFgAAAAAwABBAkAAQAaAhMAAwABBAkAAgAMAj0AAwABBAkAAwBMAlIAAwABBAkABAAcAscAAwABBAkABQAgAvQAAwABBAkABgAaAycAQwByAGUAYQB0AGUAZAAgAGIAeQAgAE4AYQB0AGgAYQBuACAARQBhAGQAeQAsACAAdQBzAGkAbgBnACAASQBuAGsAcwBjAGEAcABlACAAKABoAHQAdABwADoALwAvAHcAdwB3AC4AaQBuAGsAcwBjAGEAcABlAC4AbwByAGcAKQAgAGEAbgBkACAARgBvAG4AdABGAG8AcgBnAGUAIAAyAC4AMAAgACgAaAB0AHQAcAA6AC8ALwBmAG8AbgB0AGYAbwByAGcAZQAuAHMAZgAuAG4AZQB0ACkALgAgACAAVABoAGkAcwAgAGYAbwBuAHQAIABoAGEAcwAgAGIAZQBlAG4AIAByAGUAbABlAGEAcwBlAGQAIABpAG4AdABvACAAdABoAGUAIABwAHUAYgBsAGkAYwAgAGQAbwBtAGEAaQBuACAAYgB5ACAAdABoAGUAIABhAHUAdABoAG8AcgAuAABDcmVhdGVkIGJ5IE5hdGhhbiBFYWR5LCB1c2luZyBJbmtzY2FwZSAoaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcpIGFuZCBGb250Rm9yZ2UgMi4wIChodHRwOi8vZm9udGZvcmdlLnNmLm5ldCkuICBUaGlzIGZvbnQgaGFzIGJlZW4gcmVsZWFzZWQgaW50byB0aGUgcHVibGljIGRvbWFpbiBieSB0aGUgYXV0aG9yLgAAQgBsAG8AbwBtAGkAbgBnAEcAcgBvAHYAZQAAQmxvb21pbmdHcm92ZQAATQBlAGQAaQB1AG0AAE1lZGl1bQAARgBvAG4AdABGAG8AcgBnAGUAIAA6ACAAQgBsAG8AbwBtAGkAbgBnACAARwByAG8AdgBlACAAOgAgADkALQAxADAALQAyADAAMAA5AABGb250Rm9yZ2UgOiBCbG9vbWluZyBHcm92ZSA6IDktMTAtMjAwOQAAQgBsAG8AbwBtAGkAbgBnACAARwByAG8AdgBlAABCbG9vbWluZyBHcm92ZQAAVgBlAHIAcwBpAG8AbgAgADAAMAA2AC4AMAAwADAAIAAAVmVyc2lvbiAwMDYuMDAwIAAAQgBsAG8AbwBtAGkAbgBnAEcAcgBvAHYAZQAAQmxvb21pbmdHcm92ZQAAAAIAAAAAAAD/nAAyAAAAAAAAAAAAAAAAAAAAAAAAAAAAdwAAAQIAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAAVABYAFwAYABkAGgAbABwAHQAeAB8AIAAhACIAIwAkACUAJgAnACgAKQAqACsALAAtAC4ALwAwADEAMgAzADQANQA2ADcAOAA5ADoAOwA8AD0APgA/AEAAQQBCAEMARABFAEYARwBIAEkASgBLAEwATQBOAE8AUABRAFIAUwBUAFUAVgBXAFgAWQBaAFsAXABdAF4AXwBgAGEAowCEAOgAhgCLAIoAgwCTAKIBAwEEAQUBBgEHAIwBCAEJAQoBCwEMAQ0HdW5pMDAwMA91bmNyb3NzZWRfc2V2ZW4OdW5jcm9zc2VkX3plcm8LdW5jcm9zc2VkX3oLdW5jcm9zc2VkX1oVZ2x5cGhfZGVzaWduX3RlbXBsYXRlD2lfYWx0ZXJuYXRlLjI2Mg9qX2FsdGVybmF0ZS4yNjMGRXQuMjY0D3dfYWx0ZXJuYXRlLjI2NQ9XX2FsdGVybmF0ZS4yNjYPTV9hbHRlcm5hdGUuMjY3AAAAAf//AAIAAAABAAAAAMbCNwkAAAAAxr0CEAAAAADG2KjA
================================================
FILE: cli/test/fixtures/stylesheets/busted_font_urls/config.rb
================================================
# Require any additional compass plugins here.
project_type = :stand_alone
css_dir = "tmp"
sass_dir = "sass"
fonts_dir = "fonts"
output_style = :compact
# To enable relative image paths using the images_url() function:
# http_images_path = :relative
http_fonts_path = "/fonts"
line_comments = false
asset_cache_buster do |path, file|
pathname = Pathname.new(path)
dirname = pathname.dirname
basename = pathname.basename(pathname.extname)
extname = pathname.extname
case pathname.basename(pathname.extname).to_s
when "grid"
new_path = "#{dirname}/#{basename}-BUSTED#{extname}"
{:path => new_path, :query => nil}
when "feed"
"query_string"
when "dk"
{:query => "query_string"}
end
end
asset_host do |path|
"http://assets%d.example.com" % (path.size % 4)
end
================================================
FILE: cli/test/fixtures/stylesheets/busted_font_urls/css/screen.css
================================================
.showgrid { font-family: url('http://assets3.example.com/fonts/grid-BUSTED.ttf'); }
.no-buster { font-family: url('http://assets3.example.com/fonts/grid.ttf'); }
.buster-by-default { font-family: url('http://assets3.example.com/fonts/grid-BUSTED.ttf'); }
.feed { font-family: url('http://assets3.example.com/fonts/feed.ttf?query_string'); }
.dk { font-family: url('http://assets1.example.com/fonts/sub/dk.ttf?query_string'); }
================================================
FILE: cli/test/fixtures/stylesheets/busted_font_urls/sass/screen.sass
================================================
.showgrid
font-family: font-url("grid.ttf", $only-path: false, $cache-buster: true)
.no-buster
font-family: font-url("grid.ttf", $only-path: false, $cache-buster: false)
.buster-by-default
font-family: font-url("grid.ttf")
.feed
font-family: font-url("feed.ttf", $only-path: false, $cache-buster: true)
.dk
font-family: font-url("sub/dk.ttf", $only-path: false, $cache-buster: true)
================================================
FILE: cli/test/fixtures/stylesheets/busted_image_urls/config.rb
================================================
# Require any additional compass plugins here.
project_type = :stand_alone
css_dir = "tmp"
sass_dir = "sass"
images_dir = "images"
output_style = :compact
# To enable relative image paths using the images_url() function:
# http_images_path = :relative
http_images_path = "/images"
line_comments = false
asset_cache_buster do |path, file|
pathname = Pathname.new(path)
case pathname.basename(pathname.extname).to_s
when "grid"
new_path = "%s/%s-BUSTED%s" % [pathname.dirname, pathname.basename(pathname.extname), pathname.extname]
{:path => new_path, :query => nil}
when "feed"
"query_string"
when "dk"
{:query => "query_string"}
end
end
asset_host do |path|
"http://assets%d.example.com" % (path.size % 4)
end
================================================
FILE: cli/test/fixtures/stylesheets/busted_image_urls/css/screen.css
================================================
.showgrid { background-image: url('http://assets0.example.com/images/grid-BUSTED.png'); }
.inlinegrid { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAUEAYAAACv1qP4AAAABmJLR0T///////8JWPfcAAAACXBIWXMAAABIAAAASABGyWs+AAAAZ0lEQVRYw+3QwQ2AIBAFUTEUwI3+uzN7gDscsIgxEuO8An52J11X73OudfxMraXkzHfO3Y98nQEhA0IGhAwIGRAyIGRAyICQASEDQgaEDAgZEDIgZEDIgJABoZzSGK3tPuN9ERFP7Nw4fg+c5g8V1wAAAABJRU5ErkJggg=='); }
.no-buster { background-image: url('http://assets0.example.com/images/grid.png'); }
.feed { background-image: url('http://assets0.example.com/images/feed.png?query_string'); }
.dk { background-image: url('http://assets0.example.com/images/flags/dk.png?query_string'); }
================================================
FILE: cli/test/fixtures/stylesheets/busted_image_urls/sass/screen.sass
================================================
.showgrid
background-image: image-url("grid.png")
.inlinegrid
background-image: inline-image("grid.png")
.no-buster
background-image: image-url("grid.png", $only-path: false, $cache-buster: false)
.feed
background-image: image-url("feed.png")
.dk
background-image: image-url("flags/dk.png")
================================================
FILE: cli/test/fixtures/stylesheets/compass/config.rb
================================================
# Require any additional compass plugins here.
require 'true'
require 'compass/import-once/activate'
project_type = :stand_alone
css_dir = "tmp"
sass_dir = "sass"
images_dir = "images"
output_style = :nested
# To enable relative image paths using the images_url() function:
# http_images_path = :relative
http_images_path = "/images"
line_comments = false
asset_cache_buster do |path, file|
"busted=true"
end
disable_warnings = true
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/animation-with-legacy-ie.css
================================================
@-moz-keyframes test {
0%, 100% {
opacity: 1; }
50% {
opacity: 0; } }
@-webkit-keyframes test {
0%, 100% {
opacity: 1; }
50% {
opacity: 0; } }
@keyframes test {
0%, 100% {
opacity: 1; }
50% {
opacity: 0; } }
.animation {
-moz-animation: test;
-webkit-animation: test;
animation: test; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/animation.css
================================================
@-moz-keyframes test {
0%, 100% {
background-color: red; }
50% {
background-color: blue; } }
@-webkit-keyframes test {
0%, 100% {
background-color: red; }
50% {
background-color: blue; } }
@keyframes test {
0%, 100% {
background-color: red; }
50% {
background-color: blue; } }
.animation {
-moz-animation: test;
-webkit-animation: test;
animation: test; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/appearance.css
================================================
.searchfield {
-moz-appearance: searchfield;
-webkit-appearance: searchfield; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/background-clip.css
================================================
.background-clip {
-moz-background-clip: border;
-o-background-clip: border-box;
-webkit-background-clip: border;
background-clip: border-box; }
.background-clip-multiple {
-moz-background-clip: border, padding, content;
-o-background-clip: border-box, padding-box, content-box;
-webkit-background-clip: border, padding, content;
background-clip: border-box, padding-box, content-box; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/background-origin.css
================================================
.background-origin {
-moz-background-origin: border;
-o-background-origin: border-box;
-webkit-background-origin: border;
background-origin: border-box; }
.background-origin-multiple {
-moz-background-origin: border, padding, content;
-o-background-origin: border-box, padding-box, content-box;
-webkit-background-origin: border, padding, content;
background-origin: border-box, padding-box, content-box; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/background-size.css
================================================
.background-size-default {
-moz-background-size: 100% auto;
-o-background-size: 100% auto;
-webkit-background-size: 100% auto;
background-size: 100% auto; }
.background-size-single {
-moz-background-size: 50% 25%;
-o-background-size: 50% 25%;
-webkit-background-size: 50% 25%;
background-size: 50% 25%; }
.background-size-multiple {
-moz-background-size: 4em 3em, 100% auto, 50%;
-o-background-size: 4em 3em, 100% auto, 50%;
-webkit-background-size: 4em 3em, 100% auto, 50%;
background-size: 4em 3em, 100% auto, 50%; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/border_radius.css
================================================
.simple {
-moz-border-radius: 4px / 4px;
-webkit-border-radius: 4px 4px;
border-radius: 4px / 4px; }
.compound {
-moz-border-radius: 2px 5px / 3px 6px;
-webkit-border-radius: 2px 3px;
border-radius: 2px 5px / 3px 6px; }
.crazy {
-moz-border-radius: 1px 3px 5px 7px / 2px 4px 6px 8px;
-webkit-border-radius: 1px 2px;
border-radius: 1px 3px 5px 7px / 2px 4px 6px 8px; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/box-sizing.css
================================================
.div {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box; }
.div {
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box;
box-sizing: content-box; }
.div {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/box.css
================================================
.hbox {
display: -webkit-box;
display: -moz-box;
display: -ms-box;
display: box;
-webkit-box-orient: horizontal;
-moz-box-orient: horizontal;
-ms-box-orient: horizontal;
box-orient: horizontal;
-webkit-box-align: stretch;
-moz-box-align: stretch;
-ms-box-align: stretch;
box-align: stretch; }
.hbox > * {
-webkit-box-flex: 0;
-moz-box-flex: 0;
-ms-box-flex: 0;
box-flex: 0; }
.vbox {
display: -webkit-box;
display: -moz-box;
display: -ms-box;
display: box;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-ms-box-orient: vertical;
box-orient: vertical;
-webkit-box-align: stretch;
-moz-box-align: stretch;
-ms-box-align: stretch;
box-align: stretch; }
.vbox > * {
-webkit-box-flex: 0;
-moz-box-flex: 0;
-ms-box-flex: 0;
box-flex: 0; }
.spacer {
-webkit-box-flex: 1;
-moz-box-flex: 1;
-ms-box-flex: 1;
box-flex: 1; }
.reverse {
-webkit-box-direction: reverse;
-moz-box-direction: reverse;
-ms-box-direction: reverse;
box-direction: reverse; }
.box-flex-0 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
-ms-box-flex: 0;
box-flex: 0; }
.box-flex-1 {
-webkit-box-flex: 1;
-moz-box-flex: 1;
-ms-box-flex: 1;
box-flex: 1; }
.box-flex-2 {
-webkit-box-flex: 2;
-moz-box-flex: 2;
-ms-box-flex: 2;
box-flex: 2; }
.box-flex-group-0 {
-webkit-box-flex-group: 0;
-moz-box-flex-group: 0;
-ms-box-flex-group: 0;
box-flex-group: 0; }
.box-flex-group-1 {
-webkit-box-flex-group: 1;
-moz-box-flex-group: 1;
-ms-box-flex-group: 1;
box-flex-group: 1; }
.box-flex-group-2 {
-webkit-box-flex-group: 2;
-moz-box-flex-group: 2;
-ms-box-flex-group: 2;
box-flex-group: 2; }
.start {
-webkit-box-pack: start;
-moz-box-pack: start;
-ms-box-pack: start;
box-pack: start; }
.end {
-webkit-box-pack: end;
-moz-box-pack: end;
-ms-box-pack: end;
box-pack: end; }
.center {
-webkit-box-pack: center;
-moz-box-pack: center;
-ms-box-pack: center;
box-pack: center; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/box_shadow.css
================================================
.no-box-shadow {
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none; }
.box-shadow {
-moz-box-shadow: 0px 0px 5px #333333, 2px 2px 5px #222222;
-webkit-box-shadow: 0px 0px 5px #333333, 2px 2px 5px #222222;
box-shadow: 0px 0px 5px #333333, 2px 2px 5px #222222; }
.single-box-shadow {
-moz-box-shadow: 0px 5px #333333;
-webkit-box-shadow: 0px 5px #333333;
box-shadow: 0px 5px #333333; }
.multiple-box-shadows {
-moz-box-shadow: 0px 0px 5px #333333, 2px 2px 5px #222222;
-webkit-box-shadow: 0px 0px 5px #333333, 2px 2px 5px #222222;
box-shadow: 0px 0px 5px #333333, 2px 2px 5px #222222; }
.legacy-single-box-shadow {
-moz-box-shadow: 0px 5px blue;
-webkit-box-shadow: 0px 5px blue;
box-shadow: 0px 5px blue; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/brightness.css
================================================
.black-is-0-percent {
brightness: 0%; }
.white-is-100-percent {
brightness: 100%; }
.green-is-58-point-7-percent {
brightness: 58.7%; }
.blue-is-11-point-4-percent {
brightness: 11.4%; }
.red-is-29-point-9-percent {
brightness: 29.9%; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/browser-support.css
================================================
.android {
versions: "2.1", "2.2", "2.3", "3", "4", "4.1", "4.2-4.3", "4.4", "4.4.3";
background-img-opts: -webkit;
background-img-opts-unprefixed-at: "3";
border-image: -webkit;
border-image-unprefixed-at: "4.4";
border-radius: -webkit;
border-radius-unprefixed-at: "2.2";
css-animation: -webkit;
css-appearance: -webkit;
css-boxshadow: -webkit;
css-boxshadow-unprefixed-at: "4";
css-canvas: -webkit;
css-filters: -webkit;
css-gradients: -webkit;
css-gradients-unprefixed-at: "4.4";
css-masks: -webkit;
css-placeholder: -webkit;
css-reflections: -webkit;
css-repeating-gradients: -webkit;
css-repeating-gradients-unprefixed-at: "4.4";
css-transitions: -webkit;
css-transitions-unprefixed-at: "4.4";
css3-boxsizing: -webkit;
css3-boxsizing-unprefixed-at: "4";
font-feature: -webkit;
intrinsic-width: -webkit;
multicolumn: -webkit;
text-stroke: -webkit;
transforms2d: -webkit;
transforms3d: -webkit;
user-select-none: -webkit; }
.android-chrome {
versions: "36";
css-animation: -webkit;
css-appearance: -webkit;
css-canvas: -webkit;
css-filters: -webkit;
css-masks: -webkit;
css-placeholder: -webkit;
css-reflections: -webkit;
font-feature: -webkit;
intrinsic-width: -webkit;
multicolumn: -webkit;
text-stroke: -webkit;
transforms3d: -webkit;
user-select-none: -webkit; }
.android-firefox {
versions: "31";
css-appearance: -moz;
css-hyphens: -moz;
css-placeholder: -moz;
css3-tabsize: -moz;
font-feature: -moz;
intrinsic-width: -moz;
multicolumn: -moz;
text-decoration: -moz;
text-size-adjust: -moz;
user-select-none: -moz; }
.blackberry {
versions: "7", "10";
border-image: -webkit;
border-image-unprefixed-at: "10";
calc: -webkit;
css-animation: -webkit;
css-appearance: -webkit;
css-boxshadow: -webkit;
css-boxshadow-unprefixed-at: "10";
css-canvas: -webkit;
css-filters: -webkit;
css-gradients: -webkit;
css-masks: -webkit;
css-placeholder: -webkit;
css-reflections: -webkit;
css-repeating-gradients: -webkit;
css-transitions: -webkit;
css3-boxsizing: -webkit;
css3-boxsizing-unprefixed-at: "10";
flexbox: -webkit;
font-feature: -webkit;
intrinsic-width: -webkit;
multicolumn: -webkit;
text-stroke: -webkit;
transforms2d: -webkit;
transforms3d: -webkit;
user-select-none: -webkit; }
.chrome {
versions: "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39";
border-image: -webkit;
border-image-unprefixed-at: "16";
border-radius: -webkit;
border-radius-unprefixed-at: "5";
calc: -webkit;
calc-unprefixed-at: "26";
css-animation: -webkit;
css-appearance: -webkit;
css-boxshadow: -webkit;
css-boxshadow-unprefixed-at: "10";
css-canvas: -webkit;
css-filters: -webkit;
css-gradients: -webkit;
css-gradients-unprefixed-at: "26";
css-masks: -webkit;
css-placeholder: -webkit;
css-reflections: -webkit;
css-regions: -webkit;
css-regions-unprefixed-at: "19";
css-repeating-gradients: -webkit;
css-repeating-gradients-unprefixed-at: "26";
css-transitions: -webkit;
css-transitions-unprefixed-at: "26";
css3-boxsizing: -webkit;
css3-boxsizing-unprefixed-at: "10";
flexbox: -webkit;
flexbox-unprefixed-at: "29";
font-feature: -webkit;
intrinsic-width: -webkit;
multicolumn: -webkit;
text-stroke: -webkit;
transforms2d: -webkit;
transforms2d-unprefixed-at: "36";
transforms3d: -webkit;
transforms3d-unprefixed-at: "36";
user-select-none: -webkit; }
.firefox {
versions: "2", "3", "3.5", "3.6", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34";
background-img-opts: -moz;
background-img-opts-unprefixed-at: "4";
border-image: -moz;
border-image-unprefixed-at: "15";
border-radius: -moz;
border-radius-unprefixed-at: "4";
calc: -moz;
calc-unprefixed-at: "16";
css-animation: -moz;
css-animation-unprefixed-at: "16";
css-appearance: -moz;
css-boxshadow: -moz;
css-boxshadow-unprefixed-at: "4";
css-gradients: -moz;
css-gradients-unprefixed-at: "16";
css-hyphens: -moz;
css-placeholder: -moz;
css-repeating-gradients: -moz;
css-repeating-gradients-unprefixed-at: "16";
css-resize: prefix-no-longer-needed;
css-resize-unprefixed-at: "5";
css-selection: -moz;
css-transitions: -moz;
css-transitions-unprefixed-at: "16";
css3-boxsizing: -moz;
css3-boxsizing-unprefixed-at: "29";
css3-tabsize: -moz;
font-feature: -moz;
font-feature-unprefixed-at: "32";
inline-block: prefix-no-longer-needed;
inline-block-unprefixed-at: "3";
intrinsic-width: -moz;
multicolumn: -moz;
text-decoration: -moz;
transforms2d: -moz;
transforms2d-unprefixed-at: "16";
transforms3d: -moz;
transforms3d-unprefixed-at: "16";
user-select-none: -moz; }
.ie {
versions: "5.5", "6", "7", "8", "9", "10", "11";
css-grid: -ms;
css-hyphens: -ms;
css-placeholder: -ms;
css-regions: -ms;
transforms2d: -ms;
transforms2d-unprefixed-at: "10";
user-select-none: -ms; }
.ie-mobile {
versions: "10";
css-grid: -ms;
css-placeholder: -ms;
css-regions: -ms;
text-size-adjust: -ms;
user-select-none: -ms; }
.ios-safari {
versions: "3.2", "4.0-4.1", "4.2-4.3", "5.0-5.1", "6.0-6.1", "7.0-7.1", "8";
border-image: -webkit;
border-image-unprefixed-at: "6.0-6.1";
border-radius: -webkit;
border-radius-unprefixed-at: "4.0-4.1";
calc: -webkit;
calc-unprefixed-at: "7.0-7.1";
css-animation: -webkit;
css-appearance: -webkit;
css-boxshadow: -webkit;
css-boxshadow-unprefixed-at: "5.0-5.1";
css-canvas: -webkit;
css-filters: -webkit;
css-gradients: -webkit;
css-gradients-unprefixed-at: "7.0-7.1";
css-hyphens: -webkit;
css-masks: -webkit;
css-placeholder: -webkit;
css-reflections: -webkit;
css-regions: -webkit;
css-repeating-gradients: -webkit;
css-repeating-gradients-unprefixed-at: "7.0-7.1";
css-shapes: prefix-no-longer-needed;
css-sticky: -webkit;
css-transitions: -webkit;
css-transitions-unprefixed-at: "7.0-7.1";
css3-boxsizing: -webkit;
css3-boxsizing-unprefixed-at: "5.0-5.1";
flexbox: -webkit;
intrinsic-width: -webkit;
multicolumn: -webkit;
text-size-adjust: -webkit;
text-stroke: -webkit;
transforms2d: -webkit;
transforms3d: -webkit;
user-select-none: -webkit; }
.opera {
versions: "9.5-9.6", "10.0-10.1", "10.5", "10.6", "11", "11.1", "11.5", "11.6", "12", "12.1", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24";
background-img-opts: -webkit;
background-img-opts-unprefixed-at: "10.5";
border-image: -webkit;
border-image-unprefixed-at: "15";
css-animation: -webkit;
css-appearance: -webkit;
css-canvas: -webkit;
css-filters: -webkit;
css-gradients: -webkit;
css-gradients-unprefixed-at: "12.1";
css-masks: -webkit;
css-placeholder: -webkit;
css-reflections: -webkit;
css-repeating-gradients: -webkit;
css-repeating-gradients-unprefixed-at: "12.1";
css-transitions: -webkit;
css-transitions-unprefixed-at: "12.1";
css3-tabsize: prefix-no-longer-needed;
css3-tabsize-unprefixed-at: "15";
flexbox: -webkit;
flexbox-unprefixed-at: "17";
font-feature: -webkit;
intrinsic-width: -webkit;
multicolumn: -webkit;
object-fit: prefix-no-longer-needed;
object-fit-unprefixed-at: "15";
text-overflow: prefix-no-longer-needed;
text-overflow-unprefixed-at: "11";
text-stroke: -webkit;
transforms2d: -webkit;
transforms2d-unprefixed-at: "23";
transforms3d: -webkit;
transforms3d-unprefixed-at: "23";
user-select-none: -webkit; }
.opera-mini {
versions: "5.0-7.0";
text-overflow: -o; }
.opera-mobile {
versions: "10", "11.5", "12", "12.1", "22";
border-image: -o;
border-image-unprefixed-at: "22";
css-animation: prefix-no-longer-needed;
css-appearance: prefix-no-longer-needed;
css-canvas: prefix-no-longer-needed;
css-filters: prefix-no-longer-needed;
css-gradients: prefix-no-longer-needed;
css-gradients-unprefixed-at: "12.1";
css-masks: prefix-no-longer-needed;
css-placeholder: prefix-no-longer-needed;
css-reflections: prefix-no-longer-needed;
css-repeating-gradients: prefix-no-longer-needed;
css-repeating-gradients-unprefixed-at: "12.1";
css-transitions: -o;
css-transitions-unprefixed-at: "12.1";
css3-tabsize: -o;
css3-tabsize-unprefixed-at: "22";
font-feature: prefix-no-longer-needed;
intrinsic-width: prefix-no-longer-needed;
multicolumn: prefix-no-longer-needed;
object-fit: -o;
object-fit-unprefixed-at: "22";
text-overflow: -o;
text-overflow-unprefixed-at: "12.1";
text-stroke: prefix-no-longer-needed;
transforms2d: prefix-no-longer-needed;
transforms3d: prefix-no-longer-needed;
user-select-none: prefix-no-longer-needed; }
.safari {
versions: "3.1", "3.2", "4", "5", "5.1", "6", "6.1", "7", "8";
border-image: -webkit;
border-image-unprefixed-at: "6";
border-radius: -webkit;
border-radius-unprefixed-at: "5";
calc: -webkit;
calc-unprefixed-at: "6.1";
css-animation: -webkit;
css-appearance: -webkit;
css-boxshadow: -webkit;
css-boxshadow-unprefixed-at: "5.1";
css-canvas: -webkit;
css-filters: -webkit;
css-gradients: -webkit;
css-gradients-unprefixed-at: "6.1";
css-hyphens: -webkit;
css-masks: -webkit;
css-placeholder: -webkit;
css-reflections: -webkit;
css-regions: -webkit;
css-repeating-gradients: -webkit;
css-repeating-gradients-unprefixed-at: "6.1";
css-shapes: prefix-no-longer-needed;
css-sticky: -webkit;
css-transitions: -webkit;
css-transitions-unprefixed-at: "6.1";
css3-boxsizing: -webkit;
css3-boxsizing-unprefixed-at: "5.1";
flexbox: -webkit;
intrinsic-width: -webkit;
multicolumn: -webkit;
text-stroke: -webkit;
transforms2d: -webkit;
transforms3d: -webkit;
user-select-none: -webkit; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/color.css
================================================
.handles-null {
content: "there should be no property below this one"; }
.contrasts-light {
background-color: #eeeeee;
color: black; }
.contrasts-dark {
background-color: #222222;
color: white; }
.contrasts-light-with-contrast-color-override {
background-color: #eeeeee;
color: red; }
.contrasts-dark-with-contrast-color-override {
background-color: #222222;
color: yellow; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/columns.css
================================================
.columns {
-moz-columns: 20em 5;
-webkit-columns: 20em 5;
columns: 20em 5; }
.column-count {
-moz-column-count: 5;
-webkit-column-count: 5;
column-count: 5; }
.column-gap {
-moz-column-gap: 10px;
-webkit-column-gap: 10px;
column-gap: 10px; }
.column-width {
-moz-column-width: 90px;
-webkit-column-width: 90px;
column-width: 90px; }
.column-span {
-moz-column-span: all;
-webkit-column-span: all;
column-span: all; }
.column-rule-width {
-moz-rule-width: 1px;
-webkit-rule-width: 1px;
rule-width: 1px; }
.column-rule-style {
-moz-rule-style: dotted;
-webkit-rule-style: dotted;
rule-style: dotted; }
.column-rule-color {
-moz-rule-color: blue;
-webkit-rule-color: blue;
rule-color: blue; }
.column-rule {
-moz-column-rule: 1px solid blue;
-webkit-column-rule: 1px solid blue;
column-rule: 1px solid blue; }
.column-rule-spaced {
-moz-column-rule: 1px solid blue;
-webkit-column-rule: 1px solid blue;
column-rule: 1px solid blue; }
.column-break-before {
-moz-page-break-before: always;
-webkit-column-break-before: always;
break-before: always; }
.column-break-after {
-moz-page-break-after: always;
-webkit-column-break-after: always;
break-after: always; }
.column-break-inside {
-moz-page-break-inside: auto;
-webkit-column-break-inside: auto;
break-inside: auto; }
.column-count {
-moz-column-count: 5;
-webkit-column-count: 5;
column-count: 5; }
.column-gap {
-moz-column-gap: 10px;
-webkit-column-gap: 10px;
column-gap: 10px; }
.column-width {
-moz-column-width: 90px;
-webkit-column-width: 90px;
column-width: 90px; }
.column-rule-width {
-moz-rule-width: 1px;
-webkit-rule-width: 1px;
rule-width: 1px; }
.column-rule-style {
-moz-rule-style: dotted;
-webkit-rule-style: dotted;
rule-style: dotted; }
.column-rule-color {
-moz-rule-color: blue;
-webkit-rule-color: blue;
rule-color: blue; }
.column-rule {
-moz-column-rule: 1px solid blue;
-webkit-column-rule: 1px solid blue;
column-rule: 1px solid blue; }
.column-rule-spaced {
-moz-column-rule: 1px solid blue;
-webkit-column-rule: 1px solid blue;
column-rule: 1px solid blue; }
.column-break-before {
-moz-page-break-before: always;
-webkit-column-break-before: always;
break-before: always; }
.column-break-after {
-moz-page-break-after: always;
-webkit-column-break-after: always;
break-after: always; }
.column-break-inside {
-moz-page-break-inside: auto;
-webkit-column-break-inside: auto;
break-inside: auto; }
.column-break-before-shortcut {
-moz-page-break-before: always;
-webkit-column-break-before: always;
break-before: always; }
.column-break-after-shortcut {
-moz-page-break-after: always;
-webkit-column-break-after: always;
break-after: always; }
.column-break-inside-shortcut {
-moz-page-break-inside: auto;
-webkit-column-break-inside: auto;
break-inside: auto; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/filters.css
================================================
.blur {
/* Capability css-filters is not prefixed with -moz because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is not prefixed with -ms because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is not prefixed with -o because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is prefixed with -webkit because 50.0928% of users need it which is more than the threshold of 0.1%. */
/* Creating new -webkit context. */
-webkit-filter: blur(5px);
filter: blur(5px); }
.brightness {
/* Capability css-filters is not prefixed with -moz because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is not prefixed with -ms because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is not prefixed with -o because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is prefixed with -webkit because 50.0928% of users need it which is more than the threshold of 0.1%. */
/* Creating new -webkit context. */
-webkit-filter: brightness(0.2);
filter: brightness(0.2); }
.hue-rotate {
/* Capability css-filters is not prefixed with -moz because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is not prefixed with -ms because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is not prefixed with -o because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is prefixed with -webkit because 50.0928% of users need it which is more than the threshold of 0.1%. */
/* Creating new -webkit context. */
-webkit-filter: hue-rotate(20deg);
filter: hue-rotate(20deg); }
.contrast {
/* Capability css-filters is not prefixed with -moz because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is not prefixed with -ms because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is not prefixed with -o because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is prefixed with -webkit because 50.0928% of users need it which is more than the threshold of 0.1%. */
/* Creating new -webkit context. */
-webkit-filter: contrast(150%);
filter: contrast(150%); }
.grayscale {
/* Capability css-filters is not prefixed with -moz because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is not prefixed with -ms because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is not prefixed with -o because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is prefixed with -webkit because 50.0928% of users need it which is more than the threshold of 0.1%. */
/* Creating new -webkit context. */
-webkit-filter: grayscale(150%);
filter: grayscale(150%); }
.sepia {
/* Capability css-filters is not prefixed with -moz because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is not prefixed with -ms because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is not prefixed with -o because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-filters is prefixed with -webkit because 50.0928% of users need it which is more than the threshold of 0.1%. */
/* Creating new -webkit context. */
-webkit-filter: sepia(150%);
filter: sepia(150%); }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/flexbox.css
================================================
.display {
display: -webkit-flex;
display: flex; }
.flex-direction {
-webkit-flex-direction: row-reverse;
flex-direction: row-reverse; }
.flex-wrap {
-webkit-flex-wrap: wrap-reverse;
flex-wrap: wrap-reverse; }
.flex-flow {
-webkit-flex-flow: row-reverse wrap-reverse;
flex-flow: row-reverse wrap-reverse; }
.order {
-webkit-order: 1;
order: 1; }
.flex {
-webkit-flex: 1 0 auto;
flex: 1 0 auto; }
.flex-grow {
-webkit-flex-grow: 1;
flex-grow: 1; }
.flex-shrink {
-webkit-flex-shrink: 1;
flex-shrink: 1; }
.flex-basis {
-webkit-flex-basis: auto;
flex-basis: auto; }
.justify-content {
-webkit-justify-content: flex-start;
justify-content: flex-start; }
.align-items {
-webkit-align-items: flex-start;
align-items: flex-start; }
.align-self {
-webkit-align-self: flex-start;
align-self: flex-start; }
.align-content {
-webkit-align-content: flex-start;
align-content: flex-start; }
.flexbox {
display: -webkit-flex;
-webkit-flex-direction: row-reverse;
-webkit-flex-wrap: wrap-reverse;
-webkit-flex-flow: row-reverse wrap-reverse;
-webkit-order: 1;
-webkit-flex: 1 0 auto;
-webkit-flex-grow: 1;
-webkit-flex-shrink: 0;
-webkit-flex-basis: auto;
-webkit-justify-content: flex-start;
-webkit-align-items: flex-start;
-webkit-align-self: flex-start;
-webkit-align-content: flex-start;
display: flex;
flex-direction: row-reverse;
flex-wrap: wrap-reverse;
flex-flow: row-reverse wrap-reverse;
order: 1;
flex: 1 0 auto;
flex-grow: 1;
flex-shrink: 0;
flex-basis: auto;
justify-content: flex-start;
align-items: flex-start;
align-self: flex-start;
align-content: flex-start; }
.flexbox-2 {
display: -ms-flexbox;
-ms-flex-flow: row-reverse;
-ms-flex-order: 1; }
.flexbox-1 {
display: -moz-box;
-moz-box-orient: vertical;
-moz-box-ordinal-group: 1;
-moz-box-flex: 1;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-ordinal-group: 1;
-webkit-box-flex: 1; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/fonts.css
================================================
@font-face {
font-family: "font1";
src: url('/fonts/font1.eot?busted=true');
src: url('/fonts/font1.eot?&busted=true#iefix') format('embedded-opentype'), url('/fonts/font1.woff?busted=true') format('woff'); }
@font-face {
font-family: "Issue1491";
src: url('/fonts/font1.eot?busted=true');
src: url('/fonts/font1.eot?&busted=true#iefix') format("embedded-opentype"), url('/fonts/font1.woff?busted=true') format("woff"); }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/force-wrap.css
================================================
pre {
white-space: pre;
white-space: pre-wrap;
white-space: pre-line;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
white-space: -moz-pre-wrap;
white-space: -hp-pre-wrap;
word-wrap: break-word; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/gradients.css
================================================
.bg-shortcut-simple-image {
background: white url("foo.png"); }
.bg-shortcut-linear-gradient {
background: white url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuMCIgeDI9IjEuMCIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2RkZGRkZCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2FhYWFhYSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background: white -webkit-gradient(linear, 0% 0%, 100% 100%, color-stop(0%, #dddddd), color-stop(100%, #aaaaaa));
background: white -moz-linear-gradient(top left, #dddddd, #aaaaaa);
background: white -webkit-linear-gradient(top left, #dddddd, #aaaaaa);
background: white linear-gradient(to bottom right, #dddddd, #aaaaaa); }
.bg-shortcut-radial-gradient {
background: white url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHJhZGlhbEdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY3g9IjUwJSIgY3k9IjUwJSIgcj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2RkZGRkZCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2FhYWFhYSIvPjwvcmFkaWFsR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background: white -moz-radial-gradient(center center, #dddddd, #aaaaaa 100px);
background: white -webkit-radial-gradient(center center, #dddddd, #aaaaaa 100px);
background: white radial-gradient(center center, #dddddd, #aaaaaa 100px); }
.bg-linear-gradient-angle-svg {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjEuMCIgeTE9IjEuMCIgeDI9IjAuMCIgeTI9IjAuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDBmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
background-image: -moz-linear-gradient(135deg, #0000ff, #000000);
background-image: -webkit-linear-gradient(135deg, #0000ff, #000000);
background-image: linear-gradient(-45deg, #0000ff, #000000); }
.bg-linear-gradient-angle2-svg {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuMCIgeDI9IjEuMCIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDBmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
background-image: -webkit-gradient(linear, 0% 0%, 100% 100%, color-stop(0%, #0000ff), color-stop(100%, #000000));
background-image: -moz-linear-gradient(top left, #0000ff, #000000);
background-image: -webkit-linear-gradient(top left, #0000ff, #000000);
background-image: linear-gradient(to bottom right, #0000ff, #000000); }
.bg-all-gradient-types-with-simplification {
background: #ffcc00;
background: url('/images/4x6.png?busted=true'), url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuMCIgeDI9IjEuMCIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2RkZGRkZCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2FhYWFhYSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='), url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHJhZGlhbEdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY3g9IjUwJSIgY3k9IjUwJSIgcj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2RkZGRkZCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2FhYWFhYSIvPjwvcmFkaWFsR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='), #ffcc00;
background: url('/images/4x6.png?busted=true'), -webkit-gradient(linear, 0% 0%, 100% 100%, color-stop(0%, #dddddd), color-stop(100%, #aaaaaa)), radial-gradient(center center, #dddddd, #aaaaaa 100px), #ffcc00;
background: url('/images/4x6.png?busted=true'), -moz-linear-gradient(top left, #dddddd, #aaaaaa), -moz-radial-gradient(center center, #dddddd, #aaaaaa 100px), #ffcc00;
background: url('/images/4x6.png?busted=true'), -webkit-linear-gradient(top left, #dddddd, #aaaaaa), -webkit-radial-gradient(center center, #dddddd, #aaaaaa 100px), #ffcc00;
background: url('/images/4x6.png?busted=true'), linear-gradient(to bottom right, #dddddd, #aaaaaa), radial-gradient(center center, #dddddd, #aaaaaa 100px), #ffcc00; }
.bg-simple-image {
background-image: url("foo.png"); }
.bg-linear-gradient {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuMCIgeDI9IjEuMCIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2RkZGRkZCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2FhYWFhYSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
background-image: -webkit-gradient(linear, 0% 0%, 100% 100%, color-stop(0%, #dddddd), color-stop(100%, #aaaaaa));
background-image: -moz-linear-gradient(top left, #dddddd, #aaaaaa);
background-image: -webkit-linear-gradient(top left, #dddddd, #aaaaaa);
background-image: linear-gradient(to bottom right, #dddddd, #aaaaaa); }
.bg-linear-gradient-pixel-stop-from-top {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIyNSUiIHN0b3AtY29sb3I9IiNkZGRkZGQiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNhYWFhYWEiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA=');
background-size: 100%;
background-image: -webkit-gradient(linear, 50% 0%, 50% 40, color-stop(25%, #dddddd), color-stop(100%, #aaaaaa));
background-image: -moz-linear-gradient(top, #dddddd 10px, #aaaaaa 40px);
background-image: -webkit-linear-gradient(top, #dddddd 10px, #aaaaaa 40px);
background-image: linear-gradient(to bottom, #dddddd 10px, #aaaaaa 40px); }
.bg-linear-gradient-pixel-stop-from-left {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuNSIgeDI9IjEuMCIgeTI9IjAuNSI+PHN0b3Agb2Zmc2V0PSIyNSUiIHN0b3AtY29sb3I9IiNkZGRkZGQiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNhYWFhYWEiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA=');
background-size: 100%;
background-image: -webkit-gradient(linear, 0% 50%, 40 50%, color-stop(25%, #dddddd), color-stop(100%, #aaaaaa));
background-image: -moz-linear-gradient(left, #dddddd 10px, #aaaaaa 40px);
background-image: -webkit-linear-gradient(left, #dddddd 10px, #aaaaaa 40px);
background-image: linear-gradient(to right, #dddddd 10px, #aaaaaa 40px); }
.transparent-in-linear-gradient {
background-image: white url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuMCIgeDI9IjEuMCIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNhYWFhYWEiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA=');
background-size: 100%;
background-image: white -webkit-gradient(linear, 0% 0%, 100% 100%, color-stop(0%, rgba(0, 0, 0, 0)), color-stop(100%, #aaaaaa));
background-image: white -moz-linear-gradient(top left, rgba(0, 0, 0, 0), #aaaaaa);
background-image: white -webkit-linear-gradient(top left, rgba(0, 0, 0, 0), #aaaaaa);
background-image: white linear-gradient(to bottom right, rgba(0, 0, 0, 0), #aaaaaa); }
.currentColor-in-linear-gradient {
background-image: white url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuMCIgeDI9IjEuMCIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9ImN1cnJlbnRDb2xvciIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
background-image: white -webkit-gradient(linear, 0% 0%, 100% 100%, color-stop(0%, rgba(0, 0, 0, 0)), color-stop(100%, currentColor));
background-image: white -moz-linear-gradient(top left, rgba(0, 0, 0, 0), currentColor);
background-image: white -webkit-linear-gradient(top left, rgba(0, 0, 0, 0), currentColor);
background-image: white linear-gradient(to bottom right, rgba(0, 0, 0, 0), currentColor); }
.rgba-in-linear-gradient {
background-image: white url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuMCIgeDI9IjEuMCIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIgc3RvcC1vcGFjaXR5PSIwLjgiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4xIi8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');
background-size: 100%;
background-image: white -webkit-gradient(linear, 0% 0%, 100% 100%, color-stop(0%, rgba(255, 255, 255, 0.8)), color-stop(100%, rgba(0, 0, 0, 0.1)));
background-image: white -moz-linear-gradient(top left, rgba(255, 255, 255, 0.8), rgba(0, 0, 0, 0.1));
background-image: white -webkit-linear-gradient(top left, rgba(255, 255, 255, 0.8), rgba(0, 0, 0, 0.1));
background-image: white linear-gradient(to bottom right, rgba(255, 255, 255, 0.8), rgba(0, 0, 0, 0.1)); }
.bg-radial-gradient {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHJhZGlhbEdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY3g9IjUwJSIgY3k9IjUwJSIgcj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2RkZGRkZCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48L3JhZGlhbEdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA=');
background-size: 100%;
background-image: -moz-radial-gradient(center center, #dddddd, rgba(0, 0, 0, 0) 100px);
background-image: -webkit-radial-gradient(center center, #dddddd, rgba(0, 0, 0, 0) 100px);
background-image: radial-gradient(center center, #dddddd, rgba(0, 0, 0, 0) 100px); }
.currentColor-in-radial-gradient {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHJhZGlhbEdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY3g9IjUwJSIgY3k9IjUwJSIgcj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iY3VycmVudENvbG9yIi8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjwvcmFkaWFsR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
background-image: -moz-radial-gradient(center center, currentColor, rgba(0, 0, 0, 0) 100px);
background-image: -webkit-radial-gradient(center center, currentColor, rgba(0, 0, 0, 0) 100px);
background-image: radial-gradient(center center, currentColor, rgba(0, 0, 0, 0) 100px); }
.bg-linear-gradient-with-angle {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjEuMCIgeTE9IjEuMCIgeDI9IjAuMCIgeTI9IjAuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2RkZGRkZCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2FhYWFhYSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
background-image: -moz-linear-gradient(135deg, #dddddd, #aaaaaa);
background-image: -webkit-linear-gradient(135deg, #dddddd, #aaaaaa);
background-image: linear-gradient(-45deg, #dddddd, #aaaaaa); }
.bg-radial-gradient-with-angle-and-shape {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHJhZGlhbEdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY3g9ImVsbGlwc2UiIGN5PSJjb3ZlciIgcj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2RkZGRkZCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2FhYWFhYSIvPjwvcmFkaWFsR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
background-image: -moz-radial-gradient(ellipse cover, #dddddd, #aaaaaa 100px);
background-image: -webkit-radial-gradient(ellipse cover, #dddddd, #aaaaaa 100px);
background-image: radial-gradient(ellipse cover, #dddddd, #aaaaaa 100px); }
.bg-all-gradient-types {
background-image: url('/images/4x6.png?busted=true'), url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuMCIgeDI9IjEuMCIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2RkZGRkZCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2FhYWFhYSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='), url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHJhZGlhbEdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY3g9IjUwJSIgY3k9IjUwJSIgcj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2RkZGRkZCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2FhYWFhYSIvPjwvcmFkaWFsR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
background-image: url('/images/4x6.png?busted=true'), -webkit-gradient(linear, 0% 0%, 100% 100%, color-stop(0%, #dddddd), color-stop(100%, #aaaaaa)), radial-gradient(center center, #dddddd, #aaaaaa 100px);
background-image: url('/images/4x6.png?busted=true'), -moz-linear-gradient(top left, #dddddd, #aaaaaa), -moz-radial-gradient(center center, #dddddd, #aaaaaa 100px);
background-image: url('/images/4x6.png?busted=true'), -webkit-linear-gradient(top left, #dddddd, #aaaaaa), -webkit-radial-gradient(center center, #dddddd, #aaaaaa 100px);
background-image: url('/images/4x6.png?busted=true'), linear-gradient(to bottom right, #dddddd, #aaaaaa), radial-gradient(center center, #dddddd, #aaaaaa 100px); }
.border-image-gradient {
-moz-border-image: -moz-radial-gradient(#00ff00, #ff0000 100px) 100 stretch;
-moz-border-image: radial-gradient(#00ff00, #ff0000 100px) 100 stretch;
-o-border-image: radial-gradient(#00ff00, #ff0000 100px) 100 stretch;
-webkit-border-image: -webkit-radial-gradient(#00ff00, #ff0000 100px) 100 stretch;
-webkit-border-image: radial-gradient(#00ff00, #ff0000 100px) 100 stretch;
border-image: -moz-radial-gradient(#00ff00, #ff0000 100px) 100 stretch;
border-image: -webkit-radial-gradient(#00ff00, #ff0000 100px) 100 stretch;
border-image: radial-gradient(#00ff00, #ff0000 100px) 100 stretch; }
.direct-list-image-plain {
list-style-image: url('/images/4x6.png?busted=true'); }
.shorthand-list-image-plain {
list-style: outside url('/images/4x6.png?busted=true'); }
.direct-list-image-with-gradient {
list-style-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHJhZGlhbEdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY3g9IjUwJSIgY3k9IjUwJSIgcj0iMTAlIj48c3RvcCBvZmZzZXQ9IjAlIiBzdG9wLWNvbG9yPSIjMDBmZjAwIi8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjZmYwMDAwIi8+PC9yYWRpYWxHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');
list-style-image: -moz-radial-gradient(#00ff00, #ff0000 10px);
list-style-image: -webkit-radial-gradient(#00ff00, #ff0000 10px);
list-style-image: radial-gradient(#00ff00, #ff0000 10px); }
.shorthand-list-image-with-gradient {
list-style: outside url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHJhZGlhbEdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY3g9IjUwJSIgY3k9IjUwJSIgcj0iMTAlIj48c3RvcCBvZmZzZXQ9IjAlIiBzdG9wLWNvbG9yPSIjMDBmZjAwIi8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjZmYwMDAwIi8+PC9yYWRpYWxHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');
list-style: outside -moz-radial-gradient(#00ff00, #ff0000 10px);
list-style: outside -webkit-radial-gradient(#00ff00, #ff0000 10px);
list-style: outside radial-gradient(#00ff00, #ff0000 10px); }
.content-plain {
content: "asdf"; }
.content-with-gradient {
content: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHJhZGlhbEdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY3g9IjUwJSIgY3k9IjUwJSIgcj0iMTAlIj48c3RvcCBvZmZzZXQ9IjAlIiBzdG9wLWNvbG9yPSIjMDBmZjAwIi8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjZmYwMDAwIi8+PC9yYWRpYWxHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');
content: -moz-radial-gradient(#00ff00, #ff0000 10px);
content: -webkit-radial-gradient(#00ff00, #ff0000 10px);
content: radial-gradient(#00ff00, #ff0000 10px); }
.bg-linear-gradient-no-position {
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #dddddd), color-stop(100%, #aaaaaa));
background-image: -moz-linear-gradient(#dddddd, #aaaaaa);
background-image: -webkit-linear-gradient(#dddddd, #aaaaaa);
background-image: linear-gradient(#dddddd, #aaaaaa); }
.bg-radial-gradient-no-position {
background-image: -moz-radial-gradient(#dddddd, #aaaaaa 100px);
background-image: -webkit-radial-gradient(#dddddd, #aaaaaa 100px);
background-image: radial-gradient(#dddddd, #aaaaaa 100px); }
.image-fallback {
background-image: image(-moz-radial-gradient(#dddddd, #aaaaaa 100px), url('/images/4x6.png?busted=true'), #cc0000);
background-image: -webkit-image(-webkit-radial-gradient(#dddddd, #aaaaaa 100px), url('/images/4x6.png?busted=true'), #cc0000);
background-image: image(radial-gradient(#dddddd, #aaaaaa 100px), url('/images/4x6.png?busted=true'), #cc0000); }
.cross-fade {
background-image: cross-fade(-moz-radial-gradient(#dddddd, #aaaaaa 100px), url('/images/4x6.png?busted=true'));
background-image: -webkit-cross-fade(-webkit-radial-gradient(#dddddd, #aaaaaa 100px), url('/images/4x6.png?busted=true'));
background-image: cross-fade(radial-gradient(#dddddd, #aaaaaa 100px), url('/images/4x6.png?busted=true')); }
.unknown-function-wrapper {
background: foo(-moz-radial-gradient(#dddddd, #aaaaaa 100px));
background: foo(-webkit-radial-gradient(#dddddd, #aaaaaa 100px));
background: foo(radial-gradient(#dddddd, #aaaaaa 100px)); }
.ie-horizontal-filter {
*zoom: 1;
filter: progid:DXImageTransform.Microsoft.gradient(gradientType=1, startColorstr='#FFFFFFFF', endColorstr='#FF000000'); }
.ie-vertical-filter {
*zoom: 1;
filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFFFFF', endColorstr='#FF000000'); }
.ie-alpha-filter {
*zoom: 1;
filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFFFFF', endColorstr='#00FFFFFF'); }
.linear-gradient-new {
background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ff0000), color-stop(100%, #88aa44));
background: -moz-linear-gradient(top, #ff0000 0%, #88aa44 100%);
background: -webkit-linear-gradient(top, #ff0000 0%, #88aa44 100%);
background: linear-gradient(to bottom, #ff0000 0%, #88aa44 100%); }
.linear-gradient-old {
background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ff0000), color-stop(100%, #88aa44));
background: -moz-linear-gradient(top, #ff0000 0%, #88aa44 100%);
background: -webkit-linear-gradient(top, #ff0000 0%, #88aa44 100%);
background: linear-gradient(to bottom, #ff0000 0%, #88aa44 100%); }
.linear-gradient-unknown-new {
background: -moz-linear-gradient(330deg, #ff0000 0%, #88aa44 100%);
background: -webkit-linear-gradient(330deg, #ff0000 0%, #88aa44 100%);
background: linear-gradient(120deg, #ff0000 0%, #88aa44 100%); }
.linear-gradient-unknown-old {
background: -moz-linear-gradient(120deg, #ff0000 0%, #88aa44 100%);
background: -webkit-linear-gradient(120deg, #ff0000 0%, #88aa44 100%);
background: linear-gradient(330deg, #ff0000 0%, #88aa44 100%); }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/grid_background.css
================================================
.baseline {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjEuMCIgeDI9IjAuNSIgeTI9IjAuMCI+PHN0b3Agb2Zmc2V0PSI1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjUiLz48c3RvcCBvZmZzZXQ9IjUlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
background-image: -webkit-gradient(linear, 50% 100%, 50% 0%, color-stop(5%, rgba(0, 0, 0, 0.5)), color-stop(5%, rgba(0, 0, 0, 0)));
background-image: -moz-linear-gradient(bottom, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%);
background-image: -webkit-linear-gradient(bottom, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%);
background-image: linear-gradient(to top, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%);
-moz-background-size: 100% 1.5em;
-o-background-size: 100% 1.5em;
-webkit-background-size: 100% 1.5em;
background-size: 100% 1.5em;
background-position: left top; }
.columns {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuNSIgeDI9IjEuMCIgeTI9IjAuNSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjAlIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjMuMTI1JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIzLjEyNSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI0LjE2NjY3JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjQuMTY2NjclIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjcuMjkxNjclIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjcuMjkxNjclIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iOC4zMzMzMyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI4LjMzMzMzJSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIxMS40NTgzMyUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMTEuNDU4MzMlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMTIuNSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIxMi41JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIxNS42MjUlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjE1LjYyNSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIxNi42NjY2NyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIxNi42NjY2NyUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMTkuNzkxNjclIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjE5Ljc5MTY3JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjIwLjgzMzMzJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjIwLjgzMzMzJSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIyMy45NTgzMyUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMjMuOTU4MzMlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMjUlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMjUlIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjI4LjEyNSUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMjguMTI1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjI5LjE2NjY3JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjI5LjE2NjY3JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIzMi4yOTE2NyUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMzIuMjkxNjclIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMzMuMzMzMzMlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMzMuMzMzMzMlIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjM2LjQ1ODMzJSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIzNi40NTgzMyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIzNy41JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjM3LjUlIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjQwLjYyNSUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNDAuNjI1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjQxLjY2NjY3JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjQxLjY2NjY3JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI0NC43OTE2NyUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNDQuNzkxNjclIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNDUuODMzMzMlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNDUuODMzMzMlIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjQ4Ljk1ODMzJSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI0OC45NTgzMyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI1MCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI1MCUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNTMuMTI1JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI1My4xMjUlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNTQuMTY2NjclIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNTQuMTY2NjclIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjU3LjI5MTY3JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI1Ny4yOTE2NyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI1OC4zMzMzMyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI1OC4zMzMzMyUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNjEuNDU4MzMlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjYxLjQ1ODMzJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjYyLjUlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNjIuNSUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNjUuNjI1JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI2NS42MjUlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNjYuNjY2NjclIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNjYuNjY2NjclIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjY5Ljc5MTY3JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI2OS43OTE2NyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI3MC44MzMzMyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI3MC44MzMzMyUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNzMuOTU4MzMlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjczLjk1ODMzJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9Ijc1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9Ijc1JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI3OC4xMjUlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9Ijc4LjEyNSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI3OS4xNjY2NyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI3OS4xNjY2NyUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iODIuMjkxNjclIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjgyLjI5MTY3JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjgzLjMzMzMzJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjgzLjMzMzMzJSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI4Ni40NTgzMyUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iODYuNDU4MzMlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iODcuNSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI4Ny41JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI5MC42MjUlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjkwLjYyNSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI5MS42NjY2NyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI5MS42NjY2NyUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iOTQuNzkxNjclIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9Ijk0Ljc5MTY3JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9Ijk1LjgzMzMzJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9Ijk1LjgzMzMzJSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI5OC45NTgzMyUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iOTguOTU4MzMlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA=');
background-size: 100%;
background-image: -webkit-gradient(linear, 0% 50%, 960 50%, color-stop(0%, rgba(0, 0, 0, 0)), color-stop(0%, rgba(121, 121, 229, 0.25)), color-stop(3.125%, rgba(79, 79, 221, 0.25)), color-stop(3.125%, rgba(0, 0, 0, 0)), color-stop(4.16667%, rgba(0, 0, 0, 0)), color-stop(4.16667%, rgba(121, 121, 229, 0.25)), color-stop(7.29167%, rgba(79, 79, 221, 0.25)), color-stop(7.29167%, rgba(0, 0, 0, 0)), color-stop(8.33333%, rgba(0, 0, 0, 0)), color-stop(8.33333%, rgba(121, 121, 229, 0.25)), color-stop(11.45833%, rgba(79, 79, 221, 0.25)), color-stop(11.45833%, rgba(0, 0, 0, 0)), color-stop(12.5%, rgba(0, 0, 0, 0)), color-stop(12.5%, rgba(121, 121, 229, 0.25)), color-stop(15.625%, rgba(79, 79, 221, 0.25)), color-stop(15.625%, rgba(0, 0, 0, 0)), color-stop(16.66667%, rgba(0, 0, 0, 0)), color-stop(16.66667%, rgba(121, 121, 229, 0.25)), color-stop(19.79167%, rgba(79, 79, 221, 0.25)), color-stop(19.79167%, rgba(0, 0, 0, 0)), color-stop(20.83333%, rgba(0, 0, 0, 0)), color-stop(20.83333%, rgba(121, 121, 229, 0.25)), color-stop(23.95833%, rgba(79, 79, 221, 0.25)), color-stop(23.95833%, rgba(0, 0, 0, 0)), color-stop(25%, rgba(0, 0, 0, 0)), color-stop(25%, rgba(121, 121, 229, 0.25)), color-stop(28.125%, rgba(79, 79, 221, 0.25)), color-stop(28.125%, rgba(0, 0, 0, 0)), color-stop(29.16667%, rgba(0, 0, 0, 0)), color-stop(29.16667%, rgba(121, 121, 229, 0.25)), color-stop(32.29167%, rgba(79, 79, 221, 0.25)), color-stop(32.29167%, rgba(0, 0, 0, 0)), color-stop(33.33333%, rgba(0, 0, 0, 0)), color-stop(33.33333%, rgba(121, 121, 229, 0.25)), color-stop(36.45833%, rgba(79, 79, 221, 0.25)), color-stop(36.45833%, rgba(0, 0, 0, 0)), color-stop(37.5%, rgba(0, 0, 0, 0)), color-stop(37.5%, rgba(121, 121, 229, 0.25)), color-stop(40.625%, rgba(79, 79, 221, 0.25)), color-stop(40.625%, rgba(0, 0, 0, 0)), color-stop(41.66667%, rgba(0, 0, 0, 0)), color-stop(41.66667%, rgba(121, 121, 229, 0.25)), color-stop(44.79167%, rgba(79, 79, 221, 0.25)), color-stop(44.79167%, rgba(0, 0, 0, 0)), color-stop(45.83333%, rgba(0, 0, 0, 0)), color-stop(45.83333%, rgba(121, 121, 229, 0.25)), color-stop(48.95833%, rgba(79, 79, 221, 0.25)), color-stop(48.95833%, rgba(0, 0, 0, 0)), color-stop(50%, rgba(0, 0, 0, 0)), color-stop(50%, rgba(121, 121, 229, 0.25)), color-stop(53.125%, rgba(79, 79, 221, 0.25)), color-stop(53.125%, rgba(0, 0, 0, 0)), color-stop(54.16667%, rgba(0, 0, 0, 0)), color-stop(54.16667%, rgba(121, 121, 229, 0.25)), color-stop(57.29167%, rgba(79, 79, 221, 0.25)), color-stop(57.29167%, rgba(0, 0, 0, 0)), color-stop(58.33333%, rgba(0, 0, 0, 0)), color-stop(58.33333%, rgba(121, 121, 229, 0.25)), color-stop(61.45833%, rgba(79, 79, 221, 0.25)), color-stop(61.45833%, rgba(0, 0, 0, 0)), color-stop(62.5%, rgba(0, 0, 0, 0)), color-stop(62.5%, rgba(121, 121, 229, 0.25)), color-stop(65.625%, rgba(79, 79, 221, 0.25)), color-stop(65.625%, rgba(0, 0, 0, 0)), color-stop(66.66667%, rgba(0, 0, 0, 0)), color-stop(66.66667%, rgba(121, 121, 229, 0.25)), color-stop(69.79167%, rgba(79, 79, 221, 0.25)), color-stop(69.79167%, rgba(0, 0, 0, 0)), color-stop(70.83333%, rgba(0, 0, 0, 0)), color-stop(70.83333%, rgba(121, 121, 229, 0.25)), color-stop(73.95833%, rgba(79, 79, 221, 0.25)), color-stop(73.95833%, rgba(0, 0, 0, 0)), color-stop(75%, rgba(0, 0, 0, 0)), color-stop(75%, rgba(121, 121, 229, 0.25)), color-stop(78.125%, rgba(79, 79, 221, 0.25)), color-stop(78.125%, rgba(0, 0, 0, 0)), color-stop(79.16667%, rgba(0, 0, 0, 0)), color-stop(79.16667%, rgba(121, 121, 229, 0.25)), color-stop(82.29167%, rgba(79, 79, 221, 0.25)), color-stop(82.29167%, rgba(0, 0, 0, 0)), color-stop(83.33333%, rgba(0, 0, 0, 0)), color-stop(83.33333%, rgba(121, 121, 229, 0.25)), color-stop(86.45833%, rgba(79, 79, 221, 0.25)), color-stop(86.45833%, rgba(0, 0, 0, 0)), color-stop(87.5%, rgba(0, 0, 0, 0)), color-stop(87.5%, rgba(121, 121, 229, 0.25)), color-stop(90.625%, rgba(79, 79, 221, 0.25)), color-stop(90.625%, rgba(0, 0, 0, 0)), color-stop(91.66667%, rgba(0, 0, 0, 0)), color-stop(91.66667%, rgba(121, 121, 229, 0.25)), color-stop(94.79167%, rgba(79, 79, 221, 0.25)), color-stop(94.79167%, rgba(0, 0, 0, 0)), color-stop(95.83333%, rgba(0, 0, 0, 0)), color-stop(95.83333%, rgba(121, 121, 229, 0.25)), color-stop(98.95833%, rgba(79, 79, 221, 0.25)), color-stop(98.95833%, rgba(0, 0, 0, 0)), color-stop(100%, rgba(0, 0, 0, 0)));
background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0) 0px, rgba(121, 121, 229, 0.25) 0px, rgba(79, 79, 221, 0.25) 30px, rgba(0, 0, 0, 0) 30px, rgba(0, 0, 0, 0) 40px, rgba(121, 121, 229, 0.25) 40px, rgba(79, 79, 221, 0.25) 70px, rgba(0, 0, 0, 0) 70px, rgba(0, 0, 0, 0) 80px, rgba(121, 121, 229, 0.25) 80px, rgba(79, 79, 221, 0.25) 110px, rgba(0, 0, 0, 0) 110px, rgba(0, 0, 0, 0) 120px, rgba(121, 121, 229, 0.25) 120px, rgba(79, 79, 221, 0.25) 150px, rgba(0, 0, 0, 0) 150px, rgba(0, 0, 0, 0) 160px, rgba(121, 121, 229, 0.25) 160px, rgba(79, 79, 221, 0.25) 190px, rgba(0, 0, 0, 0) 190px, rgba(0, 0, 0, 0) 200px, rgba(121, 121, 229, 0.25) 200px, rgba(79, 79, 221, 0.25) 230px, rgba(0, 0, 0, 0) 230px, rgba(0, 0, 0, 0) 240px, rgba(121, 121, 229, 0.25) 240px, rgba(79, 79, 221, 0.25) 270px, rgba(0, 0, 0, 0) 270px, rgba(0, 0, 0, 0) 280px, rgba(121, 121, 229, 0.25) 280px, rgba(79, 79, 221, 0.25) 310px, rgba(0, 0, 0, 0) 310px, rgba(0, 0, 0, 0) 320px, rgba(121, 121, 229, 0.25) 320px, rgba(79, 79, 221, 0.25) 350px, rgba(0, 0, 0, 0) 350px, rgba(0, 0, 0, 0) 360px, rgba(121, 121, 229, 0.25) 360px, rgba(79, 79, 221, 0.25) 390px, rgba(0, 0, 0, 0) 390px, rgba(0, 0, 0, 0) 400px, rgba(121, 121, 229, 0.25) 400px, rgba(79, 79, 221, 0.25) 430px, rgba(0, 0, 0, 0) 430px, rgba(0, 0, 0, 0) 440px, rgba(121, 121, 229, 0.25) 440px, rgba(79, 79, 221, 0.25) 470px, rgba(0, 0, 0, 0) 470px, rgba(0, 0, 0, 0) 480px, rgba(121, 121, 229, 0.25) 480px, rgba(79, 79, 221, 0.25) 510px, rgba(0, 0, 0, 0) 510px, rgba(0, 0, 0, 0) 520px, rgba(121, 121, 229, 0.25) 520px, rgba(79, 79, 221, 0.25) 550px, rgba(0, 0, 0, 0) 550px, rgba(0, 0, 0, 0) 560px, rgba(121, 121, 229, 0.25) 560px, rgba(79, 79, 221, 0.25) 590px, rgba(0, 0, 0, 0) 590px, rgba(0, 0, 0, 0) 600px, rgba(121, 121, 229, 0.25) 600px, rgba(79, 79, 221, 0.25) 630px, rgba(0, 0, 0, 0) 630px, rgba(0, 0, 0, 0) 640px, rgba(121, 121, 229, 0.25) 640px, rgba(79, 79, 221, 0.25) 670px, rgba(0, 0, 0, 0) 670px, rgba(0, 0, 0, 0) 680px, rgba(121, 121, 229, 0.25) 680px, rgba(79, 79, 221, 0.25) 710px, rgba(0, 0, 0, 0) 710px, rgba(0, 0, 0, 0) 720px, rgba(121, 121, 229, 0.25) 720px, rgba(79, 79, 221, 0.25) 750px, rgba(0, 0, 0, 0) 750px, rgba(0, 0, 0, 0) 760px, rgba(121, 121, 229, 0.25) 760px, rgba(79, 79, 221, 0.25) 790px, rgba(0, 0, 0, 0) 790px, rgba(0, 0, 0, 0) 800px, rgba(121, 121, 229, 0.25) 800px, rgba(79, 79, 221, 0.25) 830px, rgba(0, 0, 0, 0) 830px, rgba(0, 0, 0, 0) 840px, rgba(121, 121, 229, 0.25) 840px, rgba(79, 79, 221, 0.25) 870px, rgba(0, 0, 0, 0) 870px, rgba(0, 0, 0, 0) 880px, rgba(121, 121, 229, 0.25) 880px, rgba(79, 79, 221, 0.25) 910px, rgba(0, 0, 0, 0) 910px, rgba(0, 0, 0, 0) 920px, rgba(121, 121, 229, 0.25) 920px, rgba(79, 79, 221, 0.25) 950px, rgba(0, 0, 0, 0) 950px, rgba(0, 0, 0, 0) 960px);
background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0) 0px, rgba(121, 121, 229, 0.25) 0px, rgba(79, 79, 221, 0.25) 30px, rgba(0, 0, 0, 0) 30px, rgba(0, 0, 0, 0) 40px, rgba(121, 121, 229, 0.25) 40px, rgba(79, 79, 221, 0.25) 70px, rgba(0, 0, 0, 0) 70px, rgba(0, 0, 0, 0) 80px, rgba(121, 121, 229, 0.25) 80px, rgba(79, 79, 221, 0.25) 110px, rgba(0, 0, 0, 0) 110px, rgba(0, 0, 0, 0) 120px, rgba(121, 121, 229, 0.25) 120px, rgba(79, 79, 221, 0.25) 150px, rgba(0, 0, 0, 0) 150px, rgba(0, 0, 0, 0) 160px, rgba(121, 121, 229, 0.25) 160px, rgba(79, 79, 221, 0.25) 190px, rgba(0, 0, 0, 0) 190px, rgba(0, 0, 0, 0) 200px, rgba(121, 121, 229, 0.25) 200px, rgba(79, 79, 221, 0.25) 230px, rgba(0, 0, 0, 0) 230px, rgba(0, 0, 0, 0) 240px, rgba(121, 121, 229, 0.25) 240px, rgba(79, 79, 221, 0.25) 270px, rgba(0, 0, 0, 0) 270px, rgba(0, 0, 0, 0) 280px, rgba(121, 121, 229, 0.25) 280px, rgba(79, 79, 221, 0.25) 310px, rgba(0, 0, 0, 0) 310px, rgba(0, 0, 0, 0) 320px, rgba(121, 121, 229, 0.25) 320px, rgba(79, 79, 221, 0.25) 350px, rgba(0, 0, 0, 0) 350px, rgba(0, 0, 0, 0) 360px, rgba(121, 121, 229, 0.25) 360px, rgba(79, 79, 221, 0.25) 390px, rgba(0, 0, 0, 0) 390px, rgba(0, 0, 0, 0) 400px, rgba(121, 121, 229, 0.25) 400px, rgba(79, 79, 221, 0.25) 430px, rgba(0, 0, 0, 0) 430px, rgba(0, 0, 0, 0) 440px, rgba(121, 121, 229, 0.25) 440px, rgba(79, 79, 221, 0.25) 470px, rgba(0, 0, 0, 0) 470px, rgba(0, 0, 0, 0) 480px, rgba(121, 121, 229, 0.25) 480px, rgba(79, 79, 221, 0.25) 510px, rgba(0, 0, 0, 0) 510px, rgba(0, 0, 0, 0) 520px, rgba(121, 121, 229, 0.25) 520px, rgba(79, 79, 221, 0.25) 550px, rgba(0, 0, 0, 0) 550px, rgba(0, 0, 0, 0) 560px, rgba(121, 121, 229, 0.25) 560px, rgba(79, 79, 221, 0.25) 590px, rgba(0, 0, 0, 0) 590px, rgba(0, 0, 0, 0) 600px, rgba(121, 121, 229, 0.25) 600px, rgba(79, 79, 221, 0.25) 630px, rgba(0, 0, 0, 0) 630px, rgba(0, 0, 0, 0) 640px, rgba(121, 121, 229, 0.25) 640px, rgba(79, 79, 221, 0.25) 670px, rgba(0, 0, 0, 0) 670px, rgba(0, 0, 0, 0) 680px, rgba(121, 121, 229, 0.25) 680px, rgba(79, 79, 221, 0.25) 710px, rgba(0, 0, 0, 0) 710px, rgba(0, 0, 0, 0) 720px, rgba(121, 121, 229, 0.25) 720px, rgba(79, 79, 221, 0.25) 750px, rgba(0, 0, 0, 0) 750px, rgba(0, 0, 0, 0) 760px, rgba(121, 121, 229, 0.25) 760px, rgba(79, 79, 221, 0.25) 790px, rgba(0, 0, 0, 0) 790px, rgba(0, 0, 0, 0) 800px, rgba(121, 121, 229, 0.25) 800px, rgba(79, 79, 221, 0.25) 830px, rgba(0, 0, 0, 0) 830px, rgba(0, 0, 0, 0) 840px, rgba(121, 121, 229, 0.25) 840px, rgba(79, 79, 221, 0.25) 870px, rgba(0, 0, 0, 0) 870px, rgba(0, 0, 0, 0) 880px, rgba(121, 121, 229, 0.25) 880px, rgba(79, 79, 221, 0.25) 910px, rgba(0, 0, 0, 0) 910px, rgba(0, 0, 0, 0) 920px, rgba(121, 121, 229, 0.25) 920px, rgba(79, 79, 221, 0.25) 950px, rgba(0, 0, 0, 0) 950px, rgba(0, 0, 0, 0) 960px);
background-image: linear-gradient(to right, rgba(0, 0, 0, 0) 0px, rgba(121, 121, 229, 0.25) 0px, rgba(79, 79, 221, 0.25) 30px, rgba(0, 0, 0, 0) 30px, rgba(0, 0, 0, 0) 40px, rgba(121, 121, 229, 0.25) 40px, rgba(79, 79, 221, 0.25) 70px, rgba(0, 0, 0, 0) 70px, rgba(0, 0, 0, 0) 80px, rgba(121, 121, 229, 0.25) 80px, rgba(79, 79, 221, 0.25) 110px, rgba(0, 0, 0, 0) 110px, rgba(0, 0, 0, 0) 120px, rgba(121, 121, 229, 0.25) 120px, rgba(79, 79, 221, 0.25) 150px, rgba(0, 0, 0, 0) 150px, rgba(0, 0, 0, 0) 160px, rgba(121, 121, 229, 0.25) 160px, rgba(79, 79, 221, 0.25) 190px, rgba(0, 0, 0, 0) 190px, rgba(0, 0, 0, 0) 200px, rgba(121, 121, 229, 0.25) 200px, rgba(79, 79, 221, 0.25) 230px, rgba(0, 0, 0, 0) 230px, rgba(0, 0, 0, 0) 240px, rgba(121, 121, 229, 0.25) 240px, rgba(79, 79, 221, 0.25) 270px, rgba(0, 0, 0, 0) 270px, rgba(0, 0, 0, 0) 280px, rgba(121, 121, 229, 0.25) 280px, rgba(79, 79, 221, 0.25) 310px, rgba(0, 0, 0, 0) 310px, rgba(0, 0, 0, 0) 320px, rgba(121, 121, 229, 0.25) 320px, rgba(79, 79, 221, 0.25) 350px, rgba(0, 0, 0, 0) 350px, rgba(0, 0, 0, 0) 360px, rgba(121, 121, 229, 0.25) 360px, rgba(79, 79, 221, 0.25) 390px, rgba(0, 0, 0, 0) 390px, rgba(0, 0, 0, 0) 400px, rgba(121, 121, 229, 0.25) 400px, rgba(79, 79, 221, 0.25) 430px, rgba(0, 0, 0, 0) 430px, rgba(0, 0, 0, 0) 440px, rgba(121, 121, 229, 0.25) 440px, rgba(79, 79, 221, 0.25) 470px, rgba(0, 0, 0, 0) 470px, rgba(0, 0, 0, 0) 480px, rgba(121, 121, 229, 0.25) 480px, rgba(79, 79, 221, 0.25) 510px, rgba(0, 0, 0, 0) 510px, rgba(0, 0, 0, 0) 520px, rgba(121, 121, 229, 0.25) 520px, rgba(79, 79, 221, 0.25) 550px, rgba(0, 0, 0, 0) 550px, rgba(0, 0, 0, 0) 560px, rgba(121, 121, 229, 0.25) 560px, rgba(79, 79, 221, 0.25) 590px, rgba(0, 0, 0, 0) 590px, rgba(0, 0, 0, 0) 600px, rgba(121, 121, 229, 0.25) 600px, rgba(79, 79, 221, 0.25) 630px, rgba(0, 0, 0, 0) 630px, rgba(0, 0, 0, 0) 640px, rgba(121, 121, 229, 0.25) 640px, rgba(79, 79, 221, 0.25) 670px, rgba(0, 0, 0, 0) 670px, rgba(0, 0, 0, 0) 680px, rgba(121, 121, 229, 0.25) 680px, rgba(79, 79, 221, 0.25) 710px, rgba(0, 0, 0, 0) 710px, rgba(0, 0, 0, 0) 720px, rgba(121, 121, 229, 0.25) 720px, rgba(79, 79, 221, 0.25) 750px, rgba(0, 0, 0, 0) 750px, rgba(0, 0, 0, 0) 760px, rgba(121, 121, 229, 0.25) 760px, rgba(79, 79, 221, 0.25) 790px, rgba(0, 0, 0, 0) 790px, rgba(0, 0, 0, 0) 800px, rgba(121, 121, 229, 0.25) 800px, rgba(79, 79, 221, 0.25) 830px, rgba(0, 0, 0, 0) 830px, rgba(0, 0, 0, 0) 840px, rgba(121, 121, 229, 0.25) 840px, rgba(79, 79, 221, 0.25) 870px, rgba(0, 0, 0, 0) 870px, rgba(0, 0, 0, 0) 880px, rgba(121, 121, 229, 0.25) 880px, rgba(79, 79, 221, 0.25) 910px, rgba(0, 0, 0, 0) 910px, rgba(0, 0, 0, 0) 920px, rgba(121, 121, 229, 0.25) 920px, rgba(79, 79, 221, 0.25) 950px, rgba(0, 0, 0, 0) 950px, rgba(0, 0, 0, 0) 960px);
background-position: left top; }
.combined {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjEuMCIgeDI9IjAuNSIgeTI9IjAuMCI+PHN0b3Agb2Zmc2V0PSI1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjUiLz48c3RvcCBvZmZzZXQ9IjUlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='), url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuNSIgeDI9IjEuMCIgeTI9IjAuNSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjAlIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjMuMTI1JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIzLjEyNSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI0LjE2NjY3JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjQuMTY2NjclIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjcuMjkxNjclIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjcuMjkxNjclIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iOC4zMzMzMyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI4LjMzMzMzJSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIxMS40NTgzMyUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMTEuNDU4MzMlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMTIuNSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIxMi41JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIxNS42MjUlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjE1LjYyNSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIxNi42NjY2NyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIxNi42NjY2NyUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMTkuNzkxNjclIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjE5Ljc5MTY3JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjIwLjgzMzMzJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjIwLjgzMzMzJSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIyMy45NTgzMyUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMjMuOTU4MzMlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMjUlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMjUlIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjI4LjEyNSUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMjguMTI1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjI5LjE2NjY3JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjI5LjE2NjY3JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIzMi4yOTE2NyUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMzIuMjkxNjclIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMzMuMzMzMzMlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMzMuMzMzMzMlIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjM2LjQ1ODMzJSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIzNi40NTgzMyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIzNy41JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjM3LjUlIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjQwLjYyNSUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNDAuNjI1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjQxLjY2NjY3JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjQxLjY2NjY3JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI0NC43OTE2NyUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNDQuNzkxNjclIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNDUuODMzMzMlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNDUuODMzMzMlIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjQ4Ljk1ODMzJSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI0OC45NTgzMyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI1MCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI1MCUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNTMuMTI1JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI1My4xMjUlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNTQuMTY2NjclIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNTQuMTY2NjclIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjU3LjI5MTY3JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI1Ny4yOTE2NyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI1OC4zMzMzMyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI1OC4zMzMzMyUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNjEuNDU4MzMlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjYxLjQ1ODMzJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjYyLjUlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNjIuNSUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNjUuNjI1JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI2NS42MjUlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNjYuNjY2NjclIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNjYuNjY2NjclIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjY5Ljc5MTY3JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI2OS43OTE2NyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI3MC44MzMzMyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI3MC44MzMzMyUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNzMuOTU4MzMlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjczLjk1ODMzJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9Ijc1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9Ijc1JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI3OC4xMjUlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9Ijc4LjEyNSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI3OS4xNjY2NyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI3OS4xNjY2NyUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iODIuMjkxNjclIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjgyLjI5MTY3JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjgzLjMzMzMzJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjgzLjMzMzMzJSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI4Ni40NTgzMyUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iODYuNDU4MzMlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iODcuNSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI4Ny41JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI5MC42MjUlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjkwLjYyNSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI5MS42NjY2NyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI5MS42NjY2NyUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iOTQuNzkxNjclIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9Ijk0Ljc5MTY3JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9Ijk1LjgzMzMzJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9Ijk1LjgzMzMzJSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI5OC45NTgzMyUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iOTguOTU4MzMlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA=');
background-size: 100%;
background-image: -webkit-gradient(linear, 50% 100%, 50% 0%, color-stop(5%, rgba(0, 0, 0, 0.5)), color-stop(5%, rgba(0, 0, 0, 0))), -webkit-gradient(linear, 0% 50%, 960 50%, color-stop(0%, rgba(0, 0, 0, 0)), color-stop(0%, rgba(121, 121, 229, 0.25)), color-stop(3.125%, rgba(79, 79, 221, 0.25)), color-stop(3.125%, rgba(0, 0, 0, 0)), color-stop(4.16667%, rgba(0, 0, 0, 0)), color-stop(4.16667%, rgba(121, 121, 229, 0.25)), color-stop(7.29167%, rgba(79, 79, 221, 0.25)), color-stop(7.29167%, rgba(0, 0, 0, 0)), color-stop(8.33333%, rgba(0, 0, 0, 0)), color-stop(8.33333%, rgba(121, 121, 229, 0.25)), color-stop(11.45833%, rgba(79, 79, 221, 0.25)), color-stop(11.45833%, rgba(0, 0, 0, 0)), color-stop(12.5%, rgba(0, 0, 0, 0)), color-stop(12.5%, rgba(121, 121, 229, 0.25)), color-stop(15.625%, rgba(79, 79, 221, 0.25)), color-stop(15.625%, rgba(0, 0, 0, 0)), color-stop(16.66667%, rgba(0, 0, 0, 0)), color-stop(16.66667%, rgba(121, 121, 229, 0.25)), color-stop(19.79167%, rgba(79, 79, 221, 0.25)), color-stop(19.79167%, rgba(0, 0, 0, 0)), color-stop(20.83333%, rgba(0, 0, 0, 0)), color-stop(20.83333%, rgba(121, 121, 229, 0.25)), color-stop(23.95833%, rgba(79, 79, 221, 0.25)), color-stop(23.95833%, rgba(0, 0, 0, 0)), color-stop(25%, rgba(0, 0, 0, 0)), color-stop(25%, rgba(121, 121, 229, 0.25)), color-stop(28.125%, rgba(79, 79, 221, 0.25)), color-stop(28.125%, rgba(0, 0, 0, 0)), color-stop(29.16667%, rgba(0, 0, 0, 0)), color-stop(29.16667%, rgba(121, 121, 229, 0.25)), color-stop(32.29167%, rgba(79, 79, 221, 0.25)), color-stop(32.29167%, rgba(0, 0, 0, 0)), color-stop(33.33333%, rgba(0, 0, 0, 0)), color-stop(33.33333%, rgba(121, 121, 229, 0.25)), color-stop(36.45833%, rgba(79, 79, 221, 0.25)), color-stop(36.45833%, rgba(0, 0, 0, 0)), color-stop(37.5%, rgba(0, 0, 0, 0)), color-stop(37.5%, rgba(121, 121, 229, 0.25)), color-stop(40.625%, rgba(79, 79, 221, 0.25)), color-stop(40.625%, rgba(0, 0, 0, 0)), color-stop(41.66667%, rgba(0, 0, 0, 0)), color-stop(41.66667%, rgba(121, 121, 229, 0.25)), color-stop(44.79167%, rgba(79, 79, 221, 0.25)), color-stop(44.79167%, rgba(0, 0, 0, 0)), color-stop(45.83333%, rgba(0, 0, 0, 0)), color-stop(45.83333%, rgba(121, 121, 229, 0.25)), color-stop(48.95833%, rgba(79, 79, 221, 0.25)), color-stop(48.95833%, rgba(0, 0, 0, 0)), color-stop(50%, rgba(0, 0, 0, 0)), color-stop(50%, rgba(121, 121, 229, 0.25)), color-stop(53.125%, rgba(79, 79, 221, 0.25)), color-stop(53.125%, rgba(0, 0, 0, 0)), color-stop(54.16667%, rgba(0, 0, 0, 0)), color-stop(54.16667%, rgba(121, 121, 229, 0.25)), color-stop(57.29167%, rgba(79, 79, 221, 0.25)), color-stop(57.29167%, rgba(0, 0, 0, 0)), color-stop(58.33333%, rgba(0, 0, 0, 0)), color-stop(58.33333%, rgba(121, 121, 229, 0.25)), color-stop(61.45833%, rgba(79, 79, 221, 0.25)), color-stop(61.45833%, rgba(0, 0, 0, 0)), color-stop(62.5%, rgba(0, 0, 0, 0)), color-stop(62.5%, rgba(121, 121, 229, 0.25)), color-stop(65.625%, rgba(79, 79, 221, 0.25)), color-stop(65.625%, rgba(0, 0, 0, 0)), color-stop(66.66667%, rgba(0, 0, 0, 0)), color-stop(66.66667%, rgba(121, 121, 229, 0.25)), color-stop(69.79167%, rgba(79, 79, 221, 0.25)), color-stop(69.79167%, rgba(0, 0, 0, 0)), color-stop(70.83333%, rgba(0, 0, 0, 0)), color-stop(70.83333%, rgba(121, 121, 229, 0.25)), color-stop(73.95833%, rgba(79, 79, 221, 0.25)), color-stop(73.95833%, rgba(0, 0, 0, 0)), color-stop(75%, rgba(0, 0, 0, 0)), color-stop(75%, rgba(121, 121, 229, 0.25)), color-stop(78.125%, rgba(79, 79, 221, 0.25)), color-stop(78.125%, rgba(0, 0, 0, 0)), color-stop(79.16667%, rgba(0, 0, 0, 0)), color-stop(79.16667%, rgba(121, 121, 229, 0.25)), color-stop(82.29167%, rgba(79, 79, 221, 0.25)), color-stop(82.29167%, rgba(0, 0, 0, 0)), color-stop(83.33333%, rgba(0, 0, 0, 0)), color-stop(83.33333%, rgba(121, 121, 229, 0.25)), color-stop(86.45833%, rgba(79, 79, 221, 0.25)), color-stop(86.45833%, rgba(0, 0, 0, 0)), color-stop(87.5%, rgba(0, 0, 0, 0)), color-stop(87.5%, rgba(121, 121, 229, 0.25)), color-stop(90.625%, rgba(79, 79, 221, 0.25)), color-stop(90.625%, rgba(0, 0, 0, 0)), color-stop(91.66667%, rgba(0, 0, 0, 0)), color-stop(91.66667%, rgba(121, 121, 229, 0.25)), color-stop(94.79167%, rgba(79, 79, 221, 0.25)), color-stop(94.79167%, rgba(0, 0, 0, 0)), color-stop(95.83333%, rgba(0, 0, 0, 0)), color-stop(95.83333%, rgba(121, 121, 229, 0.25)), color-stop(98.95833%, rgba(79, 79, 221, 0.25)), color-stop(98.95833%, rgba(0, 0, 0, 0)), color-stop(100%, rgba(0, 0, 0, 0)));
background-image: -moz-linear-gradient(bottom, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%), -moz-linear-gradient(left, rgba(0, 0, 0, 0) 0px, rgba(121, 121, 229, 0.25) 0px, rgba(79, 79, 221, 0.25) 30px, rgba(0, 0, 0, 0) 30px, rgba(0, 0, 0, 0) 40px, rgba(121, 121, 229, 0.25) 40px, rgba(79, 79, 221, 0.25) 70px, rgba(0, 0, 0, 0) 70px, rgba(0, 0, 0, 0) 80px, rgba(121, 121, 229, 0.25) 80px, rgba(79, 79, 221, 0.25) 110px, rgba(0, 0, 0, 0) 110px, rgba(0, 0, 0, 0) 120px, rgba(121, 121, 229, 0.25) 120px, rgba(79, 79, 221, 0.25) 150px, rgba(0, 0, 0, 0) 150px, rgba(0, 0, 0, 0) 160px, rgba(121, 121, 229, 0.25) 160px, rgba(79, 79, 221, 0.25) 190px, rgba(0, 0, 0, 0) 190px, rgba(0, 0, 0, 0) 200px, rgba(121, 121, 229, 0.25) 200px, rgba(79, 79, 221, 0.25) 230px, rgba(0, 0, 0, 0) 230px, rgba(0, 0, 0, 0) 240px, rgba(121, 121, 229, 0.25) 240px, rgba(79, 79, 221, 0.25) 270px, rgba(0, 0, 0, 0) 270px, rgba(0, 0, 0, 0) 280px, rgba(121, 121, 229, 0.25) 280px, rgba(79, 79, 221, 0.25) 310px, rgba(0, 0, 0, 0) 310px, rgba(0, 0, 0, 0) 320px, rgba(121, 121, 229, 0.25) 320px, rgba(79, 79, 221, 0.25) 350px, rgba(0, 0, 0, 0) 350px, rgba(0, 0, 0, 0) 360px, rgba(121, 121, 229, 0.25) 360px, rgba(79, 79, 221, 0.25) 390px, rgba(0, 0, 0, 0) 390px, rgba(0, 0, 0, 0) 400px, rgba(121, 121, 229, 0.25) 400px, rgba(79, 79, 221, 0.25) 430px, rgba(0, 0, 0, 0) 430px, rgba(0, 0, 0, 0) 440px, rgba(121, 121, 229, 0.25) 440px, rgba(79, 79, 221, 0.25) 470px, rgba(0, 0, 0, 0) 470px, rgba(0, 0, 0, 0) 480px, rgba(121, 121, 229, 0.25) 480px, rgba(79, 79, 221, 0.25) 510px, rgba(0, 0, 0, 0) 510px, rgba(0, 0, 0, 0) 520px, rgba(121, 121, 229, 0.25) 520px, rgba(79, 79, 221, 0.25) 550px, rgba(0, 0, 0, 0) 550px, rgba(0, 0, 0, 0) 560px, rgba(121, 121, 229, 0.25) 560px, rgba(79, 79, 221, 0.25) 590px, rgba(0, 0, 0, 0) 590px, rgba(0, 0, 0, 0) 600px, rgba(121, 121, 229, 0.25) 600px, rgba(79, 79, 221, 0.25) 630px, rgba(0, 0, 0, 0) 630px, rgba(0, 0, 0, 0) 640px, rgba(121, 121, 229, 0.25) 640px, rgba(79, 79, 221, 0.25) 670px, rgba(0, 0, 0, 0) 670px, rgba(0, 0, 0, 0) 680px, rgba(121, 121, 229, 0.25) 680px, rgba(79, 79, 221, 0.25) 710px, rgba(0, 0, 0, 0) 710px, rgba(0, 0, 0, 0) 720px, rgba(121, 121, 229, 0.25) 720px, rgba(79, 79, 221, 0.25) 750px, rgba(0, 0, 0, 0) 750px, rgba(0, 0, 0, 0) 760px, rgba(121, 121, 229, 0.25) 760px, rgba(79, 79, 221, 0.25) 790px, rgba(0, 0, 0, 0) 790px, rgba(0, 0, 0, 0) 800px, rgba(121, 121, 229, 0.25) 800px, rgba(79, 79, 221, 0.25) 830px, rgba(0, 0, 0, 0) 830px, rgba(0, 0, 0, 0) 840px, rgba(121, 121, 229, 0.25) 840px, rgba(79, 79, 221, 0.25) 870px, rgba(0, 0, 0, 0) 870px, rgba(0, 0, 0, 0) 880px, rgba(121, 121, 229, 0.25) 880px, rgba(79, 79, 221, 0.25) 910px, rgba(0, 0, 0, 0) 910px, rgba(0, 0, 0, 0) 920px, rgba(121, 121, 229, 0.25) 920px, rgba(79, 79, 221, 0.25) 950px, rgba(0, 0, 0, 0) 950px, rgba(0, 0, 0, 0) 960px);
background-image: -webkit-linear-gradient(bottom, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%), -webkit-linear-gradient(left, rgba(0, 0, 0, 0) 0px, rgba(121, 121, 229, 0.25) 0px, rgba(79, 79, 221, 0.25) 30px, rgba(0, 0, 0, 0) 30px, rgba(0, 0, 0, 0) 40px, rgba(121, 121, 229, 0.25) 40px, rgba(79, 79, 221, 0.25) 70px, rgba(0, 0, 0, 0) 70px, rgba(0, 0, 0, 0) 80px, rgba(121, 121, 229, 0.25) 80px, rgba(79, 79, 221, 0.25) 110px, rgba(0, 0, 0, 0) 110px, rgba(0, 0, 0, 0) 120px, rgba(121, 121, 229, 0.25) 120px, rgba(79, 79, 221, 0.25) 150px, rgba(0, 0, 0, 0) 150px, rgba(0, 0, 0, 0) 160px, rgba(121, 121, 229, 0.25) 160px, rgba(79, 79, 221, 0.25) 190px, rgba(0, 0, 0, 0) 190px, rgba(0, 0, 0, 0) 200px, rgba(121, 121, 229, 0.25) 200px, rgba(79, 79, 221, 0.25) 230px, rgba(0, 0, 0, 0) 230px, rgba(0, 0, 0, 0) 240px, rgba(121, 121, 229, 0.25) 240px, rgba(79, 79, 221, 0.25) 270px, rgba(0, 0, 0, 0) 270px, rgba(0, 0, 0, 0) 280px, rgba(121, 121, 229, 0.25) 280px, rgba(79, 79, 221, 0.25) 310px, rgba(0, 0, 0, 0) 310px, rgba(0, 0, 0, 0) 320px, rgba(121, 121, 229, 0.25) 320px, rgba(79, 79, 221, 0.25) 350px, rgba(0, 0, 0, 0) 350px, rgba(0, 0, 0, 0) 360px, rgba(121, 121, 229, 0.25) 360px, rgba(79, 79, 221, 0.25) 390px, rgba(0, 0, 0, 0) 390px, rgba(0, 0, 0, 0) 400px, rgba(121, 121, 229, 0.25) 400px, rgba(79, 79, 221, 0.25) 430px, rgba(0, 0, 0, 0) 430px, rgba(0, 0, 0, 0) 440px, rgba(121, 121, 229, 0.25) 440px, rgba(79, 79, 221, 0.25) 470px, rgba(0, 0, 0, 0) 470px, rgba(0, 0, 0, 0) 480px, rgba(121, 121, 229, 0.25) 480px, rgba(79, 79, 221, 0.25) 510px, rgba(0, 0, 0, 0) 510px, rgba(0, 0, 0, 0) 520px, rgba(121, 121, 229, 0.25) 520px, rgba(79, 79, 221, 0.25) 550px, rgba(0, 0, 0, 0) 550px, rgba(0, 0, 0, 0) 560px, rgba(121, 121, 229, 0.25) 560px, rgba(79, 79, 221, 0.25) 590px, rgba(0, 0, 0, 0) 590px, rgba(0, 0, 0, 0) 600px, rgba(121, 121, 229, 0.25) 600px, rgba(79, 79, 221, 0.25) 630px, rgba(0, 0, 0, 0) 630px, rgba(0, 0, 0, 0) 640px, rgba(121, 121, 229, 0.25) 640px, rgba(79, 79, 221, 0.25) 670px, rgba(0, 0, 0, 0) 670px, rgba(0, 0, 0, 0) 680px, rgba(121, 121, 229, 0.25) 680px, rgba(79, 79, 221, 0.25) 710px, rgba(0, 0, 0, 0) 710px, rgba(0, 0, 0, 0) 720px, rgba(121, 121, 229, 0.25) 720px, rgba(79, 79, 221, 0.25) 750px, rgba(0, 0, 0, 0) 750px, rgba(0, 0, 0, 0) 760px, rgba(121, 121, 229, 0.25) 760px, rgba(79, 79, 221, 0.25) 790px, rgba(0, 0, 0, 0) 790px, rgba(0, 0, 0, 0) 800px, rgba(121, 121, 229, 0.25) 800px, rgba(79, 79, 221, 0.25) 830px, rgba(0, 0, 0, 0) 830px, rgba(0, 0, 0, 0) 840px, rgba(121, 121, 229, 0.25) 840px, rgba(79, 79, 221, 0.25) 870px, rgba(0, 0, 0, 0) 870px, rgba(0, 0, 0, 0) 880px, rgba(121, 121, 229, 0.25) 880px, rgba(79, 79, 221, 0.25) 910px, rgba(0, 0, 0, 0) 910px, rgba(0, 0, 0, 0) 920px, rgba(121, 121, 229, 0.25) 920px, rgba(79, 79, 221, 0.25) 950px, rgba(0, 0, 0, 0) 950px, rgba(0, 0, 0, 0) 960px);
background-image: linear-gradient(to top, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%), linear-gradient(to right, rgba(0, 0, 0, 0) 0px, rgba(121, 121, 229, 0.25) 0px, rgba(79, 79, 221, 0.25) 30px, rgba(0, 0, 0, 0) 30px, rgba(0, 0, 0, 0) 40px, rgba(121, 121, 229, 0.25) 40px, rgba(79, 79, 221, 0.25) 70px, rgba(0, 0, 0, 0) 70px, rgba(0, 0, 0, 0) 80px, rgba(121, 121, 229, 0.25) 80px, rgba(79, 79, 221, 0.25) 110px, rgba(0, 0, 0, 0) 110px, rgba(0, 0, 0, 0) 120px, rgba(121, 121, 229, 0.25) 120px, rgba(79, 79, 221, 0.25) 150px, rgba(0, 0, 0, 0) 150px, rgba(0, 0, 0, 0) 160px, rgba(121, 121, 229, 0.25) 160px, rgba(79, 79, 221, 0.25) 190px, rgba(0, 0, 0, 0) 190px, rgba(0, 0, 0, 0) 200px, rgba(121, 121, 229, 0.25) 200px, rgba(79, 79, 221, 0.25) 230px, rgba(0, 0, 0, 0) 230px, rgba(0, 0, 0, 0) 240px, rgba(121, 121, 229, 0.25) 240px, rgba(79, 79, 221, 0.25) 270px, rgba(0, 0, 0, 0) 270px, rgba(0, 0, 0, 0) 280px, rgba(121, 121, 229, 0.25) 280px, rgba(79, 79, 221, 0.25) 310px, rgba(0, 0, 0, 0) 310px, rgba(0, 0, 0, 0) 320px, rgba(121, 121, 229, 0.25) 320px, rgba(79, 79, 221, 0.25) 350px, rgba(0, 0, 0, 0) 350px, rgba(0, 0, 0, 0) 360px, rgba(121, 121, 229, 0.25) 360px, rgba(79, 79, 221, 0.25) 390px, rgba(0, 0, 0, 0) 390px, rgba(0, 0, 0, 0) 400px, rgba(121, 121, 229, 0.25) 400px, rgba(79, 79, 221, 0.25) 430px, rgba(0, 0, 0, 0) 430px, rgba(0, 0, 0, 0) 440px, rgba(121, 121, 229, 0.25) 440px, rgba(79, 79, 221, 0.25) 470px, rgba(0, 0, 0, 0) 470px, rgba(0, 0, 0, 0) 480px, rgba(121, 121, 229, 0.25) 480px, rgba(79, 79, 221, 0.25) 510px, rgba(0, 0, 0, 0) 510px, rgba(0, 0, 0, 0) 520px, rgba(121, 121, 229, 0.25) 520px, rgba(79, 79, 221, 0.25) 550px, rgba(0, 0, 0, 0) 550px, rgba(0, 0, 0, 0) 560px, rgba(121, 121, 229, 0.25) 560px, rgba(79, 79, 221, 0.25) 590px, rgba(0, 0, 0, 0) 590px, rgba(0, 0, 0, 0) 600px, rgba(121, 121, 229, 0.25) 600px, rgba(79, 79, 221, 0.25) 630px, rgba(0, 0, 0, 0) 630px, rgba(0, 0, 0, 0) 640px, rgba(121, 121, 229, 0.25) 640px, rgba(79, 79, 221, 0.25) 670px, rgba(0, 0, 0, 0) 670px, rgba(0, 0, 0, 0) 680px, rgba(121, 121, 229, 0.25) 680px, rgba(79, 79, 221, 0.25) 710px, rgba(0, 0, 0, 0) 710px, rgba(0, 0, 0, 0) 720px, rgba(121, 121, 229, 0.25) 720px, rgba(79, 79, 221, 0.25) 750px, rgba(0, 0, 0, 0) 750px, rgba(0, 0, 0, 0) 760px, rgba(121, 121, 229, 0.25) 760px, rgba(79, 79, 221, 0.25) 790px, rgba(0, 0, 0, 0) 790px, rgba(0, 0, 0, 0) 800px, rgba(121, 121, 229, 0.25) 800px, rgba(79, 79, 221, 0.25) 830px, rgba(0, 0, 0, 0) 830px, rgba(0, 0, 0, 0) 840px, rgba(121, 121, 229, 0.25) 840px, rgba(79, 79, 221, 0.25) 870px, rgba(0, 0, 0, 0) 870px, rgba(0, 0, 0, 0) 880px, rgba(121, 121, 229, 0.25) 880px, rgba(79, 79, 221, 0.25) 910px, rgba(0, 0, 0, 0) 910px, rgba(0, 0, 0, 0) 920px, rgba(121, 121, 229, 0.25) 920px, rgba(79, 79, 221, 0.25) 950px, rgba(0, 0, 0, 0) 950px, rgba(0, 0, 0, 0) 960px);
-moz-background-size: 100% 1.5em, auto;
-o-background-size: 100% 1.5em, auto;
-webkit-background-size: 100% 1.5em, auto;
background-size: 100% 1.5em, auto;
background-position: left top; }
.percent-baseline {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjEuMCIgeDI9IjAuNSIgeTI9IjAuMCI+PHN0b3Agb2Zmc2V0PSI1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjUiLz48c3RvcCBvZmZzZXQ9IjUlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
background-image: -webkit-gradient(linear, 50% 100%, 50% 0%, color-stop(5%, rgba(0, 0, 0, 0.5)), color-stop(5%, rgba(0, 0, 0, 0)));
background-image: -moz-linear-gradient(bottom, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%);
background-image: -webkit-linear-gradient(bottom, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%);
background-image: linear-gradient(to top, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%);
-moz-background-size: 100% 1.5em;
-o-background-size: 100% 1.5em;
-webkit-background-size: 100% 1.5em;
background-size: 100% 1.5em;
background-position: left top; }
.percent-columns {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuNSIgeDI9IjEuMCIgeTI9IjAuNSI+PHN0b3Agb2Zmc2V0PSIxMSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIxMSUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMTYlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjE2JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjE3JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjE3JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIyMiUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMjIlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMjMlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMjMlIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjI4JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIyOCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIyOSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIyOSUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMzQlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjM0JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjM1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjM1JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI0MCUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNDAlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNDElIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNDElIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjQ2JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI0NiUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI0NyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI0NyUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNTIlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjUyJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjUzJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjUzJSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI1OCUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNTglIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNTklIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNTklIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjY0JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI2NCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI2NSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI2NSUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNzAlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjcwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjcxJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjcxJSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI3NiUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNzYlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNzclIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNzclIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjgyJSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI4MiUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI4MyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI4MyUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iODglIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9Ijg4JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9Ijg5JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9Ijg5JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI5NCUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iOTQlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iOTUlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iOTUlIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');
background-size: 100%;
background-image: -webkit-gradient(linear, 0% 50%, 100% 50%, color-stop(11%, rgba(0, 0, 0, 0)), color-stop(11%, rgba(121, 121, 229, 0.25)), color-stop(16%, rgba(79, 79, 221, 0.25)), color-stop(16%, rgba(0, 0, 0, 0)), color-stop(17%, rgba(0, 0, 0, 0)), color-stop(17%, rgba(121, 121, 229, 0.25)), color-stop(22%, rgba(79, 79, 221, 0.25)), color-stop(22%, rgba(0, 0, 0, 0)), color-stop(23%, rgba(0, 0, 0, 0)), color-stop(23%, rgba(121, 121, 229, 0.25)), color-stop(28%, rgba(79, 79, 221, 0.25)), color-stop(28%, rgba(0, 0, 0, 0)), color-stop(29%, rgba(0, 0, 0, 0)), color-stop(29%, rgba(121, 121, 229, 0.25)), color-stop(34%, rgba(79, 79, 221, 0.25)), color-stop(34%, rgba(0, 0, 0, 0)), color-stop(35%, rgba(0, 0, 0, 0)), color-stop(35%, rgba(121, 121, 229, 0.25)), color-stop(40%, rgba(79, 79, 221, 0.25)), color-stop(40%, rgba(0, 0, 0, 0)), color-stop(41%, rgba(0, 0, 0, 0)), color-stop(41%, rgba(121, 121, 229, 0.25)), color-stop(46%, rgba(79, 79, 221, 0.25)), color-stop(46%, rgba(0, 0, 0, 0)), color-stop(47%, rgba(0, 0, 0, 0)), color-stop(47%, rgba(121, 121, 229, 0.25)), color-stop(52%, rgba(79, 79, 221, 0.25)), color-stop(52%, rgba(0, 0, 0, 0)), color-stop(53%, rgba(0, 0, 0, 0)), color-stop(53%, rgba(121, 121, 229, 0.25)), color-stop(58%, rgba(79, 79, 221, 0.25)), color-stop(58%, rgba(0, 0, 0, 0)), color-stop(59%, rgba(0, 0, 0, 0)), color-stop(59%, rgba(121, 121, 229, 0.25)), color-stop(64%, rgba(79, 79, 221, 0.25)), color-stop(64%, rgba(0, 0, 0, 0)), color-stop(65%, rgba(0, 0, 0, 0)), color-stop(65%, rgba(121, 121, 229, 0.25)), color-stop(70%, rgba(79, 79, 221, 0.25)), color-stop(70%, rgba(0, 0, 0, 0)), color-stop(71%, rgba(0, 0, 0, 0)), color-stop(71%, rgba(121, 121, 229, 0.25)), color-stop(76%, rgba(79, 79, 221, 0.25)), color-stop(76%, rgba(0, 0, 0, 0)), color-stop(77%, rgba(0, 0, 0, 0)), color-stop(77%, rgba(121, 121, 229, 0.25)), color-stop(82%, rgba(79, 79, 221, 0.25)), color-stop(82%, rgba(0, 0, 0, 0)), color-stop(83%, rgba(0, 0, 0, 0)), color-stop(83%, rgba(121, 121, 229, 0.25)), color-stop(88%, rgba(79, 79, 221, 0.25)), color-stop(88%, rgba(0, 0, 0, 0)), color-stop(89%, rgba(0, 0, 0, 0)), color-stop(89%, rgba(121, 121, 229, 0.25)), color-stop(94%, rgba(79, 79, 221, 0.25)), color-stop(94%, rgba(0, 0, 0, 0)), color-stop(95%, rgba(0, 0, 0, 0)), color-stop(95%, rgba(121, 121, 229, 0.25)), color-stop(100%, rgba(79, 79, 221, 0.25)), color-stop(100%, rgba(0, 0, 0, 0)), color-stop(100%, rgba(0, 0, 0, 0)));
background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0) 11%, rgba(121, 121, 229, 0.25) 11%, rgba(79, 79, 221, 0.25) 16%, rgba(0, 0, 0, 0) 16%, rgba(0, 0, 0, 0) 17%, rgba(121, 121, 229, 0.25) 17%, rgba(79, 79, 221, 0.25) 22%, rgba(0, 0, 0, 0) 22%, rgba(0, 0, 0, 0) 23%, rgba(121, 121, 229, 0.25) 23%, rgba(79, 79, 221, 0.25) 28%, rgba(0, 0, 0, 0) 28%, rgba(0, 0, 0, 0) 29%, rgba(121, 121, 229, 0.25) 29%, rgba(79, 79, 221, 0.25) 34%, rgba(0, 0, 0, 0) 34%, rgba(0, 0, 0, 0) 35%, rgba(121, 121, 229, 0.25) 35%, rgba(79, 79, 221, 0.25) 40%, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0) 41%, rgba(121, 121, 229, 0.25) 41%, rgba(79, 79, 221, 0.25) 46%, rgba(0, 0, 0, 0) 46%, rgba(0, 0, 0, 0) 47%, rgba(121, 121, 229, 0.25) 47%, rgba(79, 79, 221, 0.25) 52%, rgba(0, 0, 0, 0) 52%, rgba(0, 0, 0, 0) 53%, rgba(121, 121, 229, 0.25) 53%, rgba(79, 79, 221, 0.25) 58%, rgba(0, 0, 0, 0) 58%, rgba(0, 0, 0, 0) 59%, rgba(121, 121, 229, 0.25) 59%, rgba(79, 79, 221, 0.25) 64%, rgba(0, 0, 0, 0) 64%, rgba(0, 0, 0, 0) 65%, rgba(121, 121, 229, 0.25) 65%, rgba(79, 79, 221, 0.25) 70%, rgba(0, 0, 0, 0) 70%, rgba(0, 0, 0, 0) 71%, rgba(121, 121, 229, 0.25) 71%, rgba(79, 79, 221, 0.25) 76%, rgba(0, 0, 0, 0) 76%, rgba(0, 0, 0, 0) 77%, rgba(121, 121, 229, 0.25) 77%, rgba(79, 79, 221, 0.25) 82%, rgba(0, 0, 0, 0) 82%, rgba(0, 0, 0, 0) 83%, rgba(121, 121, 229, 0.25) 83%, rgba(79, 79, 221, 0.25) 88%, rgba(0, 0, 0, 0) 88%, rgba(0, 0, 0, 0) 89%, rgba(121, 121, 229, 0.25) 89%, rgba(79, 79, 221, 0.25) 94%, rgba(0, 0, 0, 0) 94%, rgba(0, 0, 0, 0) 95%, rgba(121, 121, 229, 0.25) 95%, rgba(79, 79, 221, 0.25) 100%, rgba(0, 0, 0, 0) 100%, rgba(0, 0, 0, 0) 100%);
background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0) 11%, rgba(121, 121, 229, 0.25) 11%, rgba(79, 79, 221, 0.25) 16%, rgba(0, 0, 0, 0) 16%, rgba(0, 0, 0, 0) 17%, rgba(121, 121, 229, 0.25) 17%, rgba(79, 79, 221, 0.25) 22%, rgba(0, 0, 0, 0) 22%, rgba(0, 0, 0, 0) 23%, rgba(121, 121, 229, 0.25) 23%, rgba(79, 79, 221, 0.25) 28%, rgba(0, 0, 0, 0) 28%, rgba(0, 0, 0, 0) 29%, rgba(121, 121, 229, 0.25) 29%, rgba(79, 79, 221, 0.25) 34%, rgba(0, 0, 0, 0) 34%, rgba(0, 0, 0, 0) 35%, rgba(121, 121, 229, 0.25) 35%, rgba(79, 79, 221, 0.25) 40%, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0) 41%, rgba(121, 121, 229, 0.25) 41%, rgba(79, 79, 221, 0.25) 46%, rgba(0, 0, 0, 0) 46%, rgba(0, 0, 0, 0) 47%, rgba(121, 121, 229, 0.25) 47%, rgba(79, 79, 221, 0.25) 52%, rgba(0, 0, 0, 0) 52%, rgba(0, 0, 0, 0) 53%, rgba(121, 121, 229, 0.25) 53%, rgba(79, 79, 221, 0.25) 58%, rgba(0, 0, 0, 0) 58%, rgba(0, 0, 0, 0) 59%, rgba(121, 121, 229, 0.25) 59%, rgba(79, 79, 221, 0.25) 64%, rgba(0, 0, 0, 0) 64%, rgba(0, 0, 0, 0) 65%, rgba(121, 121, 229, 0.25) 65%, rgba(79, 79, 221, 0.25) 70%, rgba(0, 0, 0, 0) 70%, rgba(0, 0, 0, 0) 71%, rgba(121, 121, 229, 0.25) 71%, rgba(79, 79, 221, 0.25) 76%, rgba(0, 0, 0, 0) 76%, rgba(0, 0, 0, 0) 77%, rgba(121, 121, 229, 0.25) 77%, rgba(79, 79, 221, 0.25) 82%, rgba(0, 0, 0, 0) 82%, rgba(0, 0, 0, 0) 83%, rgba(121, 121, 229, 0.25) 83%, rgba(79, 79, 221, 0.25) 88%, rgba(0, 0, 0, 0) 88%, rgba(0, 0, 0, 0) 89%, rgba(121, 121, 229, 0.25) 89%, rgba(79, 79, 221, 0.25) 94%, rgba(0, 0, 0, 0) 94%, rgba(0, 0, 0, 0) 95%, rgba(121, 121, 229, 0.25) 95%, rgba(79, 79, 221, 0.25) 100%, rgba(0, 0, 0, 0) 100%, rgba(0, 0, 0, 0) 100%);
background-image: linear-gradient(to right, rgba(0, 0, 0, 0) 11%, rgba(121, 121, 229, 0.25) 11%, rgba(79, 79, 221, 0.25) 16%, rgba(0, 0, 0, 0) 16%, rgba(0, 0, 0, 0) 17%, rgba(121, 121, 229, 0.25) 17%, rgba(79, 79, 221, 0.25) 22%, rgba(0, 0, 0, 0) 22%, rgba(0, 0, 0, 0) 23%, rgba(121, 121, 229, 0.25) 23%, rgba(79, 79, 221, 0.25) 28%, rgba(0, 0, 0, 0) 28%, rgba(0, 0, 0, 0) 29%, rgba(121, 121, 229, 0.25) 29%, rgba(79, 79, 221, 0.25) 34%, rgba(0, 0, 0, 0) 34%, rgba(0, 0, 0, 0) 35%, rgba(121, 121, 229, 0.25) 35%, rgba(79, 79, 221, 0.25) 40%, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0) 41%, rgba(121, 121, 229, 0.25) 41%, rgba(79, 79, 221, 0.25) 46%, rgba(0, 0, 0, 0) 46%, rgba(0, 0, 0, 0) 47%, rgba(121, 121, 229, 0.25) 47%, rgba(79, 79, 221, 0.25) 52%, rgba(0, 0, 0, 0) 52%, rgba(0, 0, 0, 0) 53%, rgba(121, 121, 229, 0.25) 53%, rgba(79, 79, 221, 0.25) 58%, rgba(0, 0, 0, 0) 58%, rgba(0, 0, 0, 0) 59%, rgba(121, 121, 229, 0.25) 59%, rgba(79, 79, 221, 0.25) 64%, rgba(0, 0, 0, 0) 64%, rgba(0, 0, 0, 0) 65%, rgba(121, 121, 229, 0.25) 65%, rgba(79, 79, 221, 0.25) 70%, rgba(0, 0, 0, 0) 70%, rgba(0, 0, 0, 0) 71%, rgba(121, 121, 229, 0.25) 71%, rgba(79, 79, 221, 0.25) 76%, rgba(0, 0, 0, 0) 76%, rgba(0, 0, 0, 0) 77%, rgba(121, 121, 229, 0.25) 77%, rgba(79, 79, 221, 0.25) 82%, rgba(0, 0, 0, 0) 82%, rgba(0, 0, 0, 0) 83%, rgba(121, 121, 229, 0.25) 83%, rgba(79, 79, 221, 0.25) 88%, rgba(0, 0, 0, 0) 88%, rgba(0, 0, 0, 0) 89%, rgba(121, 121, 229, 0.25) 89%, rgba(79, 79, 221, 0.25) 94%, rgba(0, 0, 0, 0) 94%, rgba(0, 0, 0, 0) 95%, rgba(121, 121, 229, 0.25) 95%, rgba(79, 79, 221, 0.25) 100%, rgba(0, 0, 0, 0) 100%, rgba(0, 0, 0, 0) 100%);
background-position: left top; }
.percent-combined {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjEuMCIgeDI9IjAuNSIgeTI9IjAuMCI+PHN0b3Agb2Zmc2V0PSI1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjUiLz48c3RvcCBvZmZzZXQ9IjUlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='), url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuNSIgeDI9IjEuMCIgeTI9IjAuNSI+PHN0b3Agb2Zmc2V0PSIxMSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIxMSUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMTYlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjE2JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjE3JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjE3JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIyMiUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMjIlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMjMlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMjMlIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjI4JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIyOCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIyOSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIyOSUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMzQlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjM0JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjM1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjM1JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI0MCUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNDAlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNDElIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNDElIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjQ2JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI0NiUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI0NyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI0NyUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNTIlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjUyJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjUzJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjUzJSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI1OCUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNTglIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNTklIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNTklIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjY0JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI2NCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI2NSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI2NSUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNzAlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjcwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjcxJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjcxJSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI3NiUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNzYlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNzclIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNzclIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjgyJSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI4MiUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI4MyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI4MyUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iODglIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9Ijg4JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9Ijg5JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9Ijg5JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI5NCUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iOTQlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iOTUlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iOTUlIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');
background-size: 100%;
background-image: -webkit-gradient(linear, 50% 100%, 50% 0%, color-stop(5%, rgba(0, 0, 0, 0.5)), color-stop(5%, rgba(0, 0, 0, 0))), -webkit-gradient(linear, 0% 50%, 100% 50%, color-stop(11%, rgba(0, 0, 0, 0)), color-stop(11%, rgba(121, 121, 229, 0.25)), color-stop(16%, rgba(79, 79, 221, 0.25)), color-stop(16%, rgba(0, 0, 0, 0)), color-stop(17%, rgba(0, 0, 0, 0)), color-stop(17%, rgba(121, 121, 229, 0.25)), color-stop(22%, rgba(79, 79, 221, 0.25)), color-stop(22%, rgba(0, 0, 0, 0)), color-stop(23%, rgba(0, 0, 0, 0)), color-stop(23%, rgba(121, 121, 229, 0.25)), color-stop(28%, rgba(79, 79, 221, 0.25)), color-stop(28%, rgba(0, 0, 0, 0)), color-stop(29%, rgba(0, 0, 0, 0)), color-stop(29%, rgba(121, 121, 229, 0.25)), color-stop(34%, rgba(79, 79, 221, 0.25)), color-stop(34%, rgba(0, 0, 0, 0)), color-stop(35%, rgba(0, 0, 0, 0)), color-stop(35%, rgba(121, 121, 229, 0.25)), color-stop(40%, rgba(79, 79, 221, 0.25)), color-stop(40%, rgba(0, 0, 0, 0)), color-stop(41%, rgba(0, 0, 0, 0)), color-stop(41%, rgba(121, 121, 229, 0.25)), color-stop(46%, rgba(79, 79, 221, 0.25)), color-stop(46%, rgba(0, 0, 0, 0)), color-stop(47%, rgba(0, 0, 0, 0)), color-stop(47%, rgba(121, 121, 229, 0.25)), color-stop(52%, rgba(79, 79, 221, 0.25)), color-stop(52%, rgba(0, 0, 0, 0)), color-stop(53%, rgba(0, 0, 0, 0)), color-stop(53%, rgba(121, 121, 229, 0.25)), color-stop(58%, rgba(79, 79, 221, 0.25)), color-stop(58%, rgba(0, 0, 0, 0)), color-stop(59%, rgba(0, 0, 0, 0)), color-stop(59%, rgba(121, 121, 229, 0.25)), color-stop(64%, rgba(79, 79, 221, 0.25)), color-stop(64%, rgba(0, 0, 0, 0)), color-stop(65%, rgba(0, 0, 0, 0)), color-stop(65%, rgba(121, 121, 229, 0.25)), color-stop(70%, rgba(79, 79, 221, 0.25)), color-stop(70%, rgba(0, 0, 0, 0)), color-stop(71%, rgba(0, 0, 0, 0)), color-stop(71%, rgba(121, 121, 229, 0.25)), color-stop(76%, rgba(79, 79, 221, 0.25)), color-stop(76%, rgba(0, 0, 0, 0)), color-stop(77%, rgba(0, 0, 0, 0)), color-stop(77%, rgba(121, 121, 229, 0.25)), color-stop(82%, rgba(79, 79, 221, 0.25)), color-stop(82%, rgba(0, 0, 0, 0)), color-stop(83%, rgba(0, 0, 0, 0)), color-stop(83%, rgba(121, 121, 229, 0.25)), color-stop(88%, rgba(79, 79, 221, 0.25)), color-stop(88%, rgba(0, 0, 0, 0)), color-stop(89%, rgba(0, 0, 0, 0)), color-stop(89%, rgba(121, 121, 229, 0.25)), color-stop(94%, rgba(79, 79, 221, 0.25)), color-stop(94%, rgba(0, 0, 0, 0)), color-stop(95%, rgba(0, 0, 0, 0)), color-stop(95%, rgba(121, 121, 229, 0.25)), color-stop(100%, rgba(79, 79, 221, 0.25)), color-stop(100%, rgba(0, 0, 0, 0)), color-stop(100%, rgba(0, 0, 0, 0)));
background-image: -moz-linear-gradient(bottom, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%), -moz-linear-gradient(left, rgba(0, 0, 0, 0) 11%, rgba(121, 121, 229, 0.25) 11%, rgba(79, 79, 221, 0.25) 16%, rgba(0, 0, 0, 0) 16%, rgba(0, 0, 0, 0) 17%, rgba(121, 121, 229, 0.25) 17%, rgba(79, 79, 221, 0.25) 22%, rgba(0, 0, 0, 0) 22%, rgba(0, 0, 0, 0) 23%, rgba(121, 121, 229, 0.25) 23%, rgba(79, 79, 221, 0.25) 28%, rgba(0, 0, 0, 0) 28%, rgba(0, 0, 0, 0) 29%, rgba(121, 121, 229, 0.25) 29%, rgba(79, 79, 221, 0.25) 34%, rgba(0, 0, 0, 0) 34%, rgba(0, 0, 0, 0) 35%, rgba(121, 121, 229, 0.25) 35%, rgba(79, 79, 221, 0.25) 40%, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0) 41%, rgba(121, 121, 229, 0.25) 41%, rgba(79, 79, 221, 0.25) 46%, rgba(0, 0, 0, 0) 46%, rgba(0, 0, 0, 0) 47%, rgba(121, 121, 229, 0.25) 47%, rgba(79, 79, 221, 0.25) 52%, rgba(0, 0, 0, 0) 52%, rgba(0, 0, 0, 0) 53%, rgba(121, 121, 229, 0.25) 53%, rgba(79, 79, 221, 0.25) 58%, rgba(0, 0, 0, 0) 58%, rgba(0, 0, 0, 0) 59%, rgba(121, 121, 229, 0.25) 59%, rgba(79, 79, 221, 0.25) 64%, rgba(0, 0, 0, 0) 64%, rgba(0, 0, 0, 0) 65%, rgba(121, 121, 229, 0.25) 65%, rgba(79, 79, 221, 0.25) 70%, rgba(0, 0, 0, 0) 70%, rgba(0, 0, 0, 0) 71%, rgba(121, 121, 229, 0.25) 71%, rgba(79, 79, 221, 0.25) 76%, rgba(0, 0, 0, 0) 76%, rgba(0, 0, 0, 0) 77%, rgba(121, 121, 229, 0.25) 77%, rgba(79, 79, 221, 0.25) 82%, rgba(0, 0, 0, 0) 82%, rgba(0, 0, 0, 0) 83%, rgba(121, 121, 229, 0.25) 83%, rgba(79, 79, 221, 0.25) 88%, rgba(0, 0, 0, 0) 88%, rgba(0, 0, 0, 0) 89%, rgba(121, 121, 229, 0.25) 89%, rgba(79, 79, 221, 0.25) 94%, rgba(0, 0, 0, 0) 94%, rgba(0, 0, 0, 0) 95%, rgba(121, 121, 229, 0.25) 95%, rgba(79, 79, 221, 0.25) 100%, rgba(0, 0, 0, 0) 100%, rgba(0, 0, 0, 0) 100%);
background-image: -webkit-linear-gradient(bottom, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%), -webkit-linear-gradient(left, rgba(0, 0, 0, 0) 11%, rgba(121, 121, 229, 0.25) 11%, rgba(79, 79, 221, 0.25) 16%, rgba(0, 0, 0, 0) 16%, rgba(0, 0, 0, 0) 17%, rgba(121, 121, 229, 0.25) 17%, rgba(79, 79, 221, 0.25) 22%, rgba(0, 0, 0, 0) 22%, rgba(0, 0, 0, 0) 23%, rgba(121, 121, 229, 0.25) 23%, rgba(79, 79, 221, 0.25) 28%, rgba(0, 0, 0, 0) 28%, rgba(0, 0, 0, 0) 29%, rgba(121, 121, 229, 0.25) 29%, rgba(79, 79, 221, 0.25) 34%, rgba(0, 0, 0, 0) 34%, rgba(0, 0, 0, 0) 35%, rgba(121, 121, 229, 0.25) 35%, rgba(79, 79, 221, 0.25) 40%, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0) 41%, rgba(121, 121, 229, 0.25) 41%, rgba(79, 79, 221, 0.25) 46%, rgba(0, 0, 0, 0) 46%, rgba(0, 0, 0, 0) 47%, rgba(121, 121, 229, 0.25) 47%, rgba(79, 79, 221, 0.25) 52%, rgba(0, 0, 0, 0) 52%, rgba(0, 0, 0, 0) 53%, rgba(121, 121, 229, 0.25) 53%, rgba(79, 79, 221, 0.25) 58%, rgba(0, 0, 0, 0) 58%, rgba(0, 0, 0, 0) 59%, rgba(121, 121, 229, 0.25) 59%, rgba(79, 79, 221, 0.25) 64%, rgba(0, 0, 0, 0) 64%, rgba(0, 0, 0, 0) 65%, rgba(121, 121, 229, 0.25) 65%, rgba(79, 79, 221, 0.25) 70%, rgba(0, 0, 0, 0) 70%, rgba(0, 0, 0, 0) 71%, rgba(121, 121, 229, 0.25) 71%, rgba(79, 79, 221, 0.25) 76%, rgba(0, 0, 0, 0) 76%, rgba(0, 0, 0, 0) 77%, rgba(121, 121, 229, 0.25) 77%, rgba(79, 79, 221, 0.25) 82%, rgba(0, 0, 0, 0) 82%, rgba(0, 0, 0, 0) 83%, rgba(121, 121, 229, 0.25) 83%, rgba(79, 79, 221, 0.25) 88%, rgba(0, 0, 0, 0) 88%, rgba(0, 0, 0, 0) 89%, rgba(121, 121, 229, 0.25) 89%, rgba(79, 79, 221, 0.25) 94%, rgba(0, 0, 0, 0) 94%, rgba(0, 0, 0, 0) 95%, rgba(121, 121, 229, 0.25) 95%, rgba(79, 79, 221, 0.25) 100%, rgba(0, 0, 0, 0) 100%, rgba(0, 0, 0, 0) 100%);
background-image: linear-gradient(to top, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%), linear-gradient(to right, rgba(0, 0, 0, 0) 11%, rgba(121, 121, 229, 0.25) 11%, rgba(79, 79, 221, 0.25) 16%, rgba(0, 0, 0, 0) 16%, rgba(0, 0, 0, 0) 17%, rgba(121, 121, 229, 0.25) 17%, rgba(79, 79, 221, 0.25) 22%, rgba(0, 0, 0, 0) 22%, rgba(0, 0, 0, 0) 23%, rgba(121, 121, 229, 0.25) 23%, rgba(79, 79, 221, 0.25) 28%, rgba(0, 0, 0, 0) 28%, rgba(0, 0, 0, 0) 29%, rgba(121, 121, 229, 0.25) 29%, rgba(79, 79, 221, 0.25) 34%, rgba(0, 0, 0, 0) 34%, rgba(0, 0, 0, 0) 35%, rgba(121, 121, 229, 0.25) 35%, rgba(79, 79, 221, 0.25) 40%, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0) 41%, rgba(121, 121, 229, 0.25) 41%, rgba(79, 79, 221, 0.25) 46%, rgba(0, 0, 0, 0) 46%, rgba(0, 0, 0, 0) 47%, rgba(121, 121, 229, 0.25) 47%, rgba(79, 79, 221, 0.25) 52%, rgba(0, 0, 0, 0) 52%, rgba(0, 0, 0, 0) 53%, rgba(121, 121, 229, 0.25) 53%, rgba(79, 79, 221, 0.25) 58%, rgba(0, 0, 0, 0) 58%, rgba(0, 0, 0, 0) 59%, rgba(121, 121, 229, 0.25) 59%, rgba(79, 79, 221, 0.25) 64%, rgba(0, 0, 0, 0) 64%, rgba(0, 0, 0, 0) 65%, rgba(121, 121, 229, 0.25) 65%, rgba(79, 79, 221, 0.25) 70%, rgba(0, 0, 0, 0) 70%, rgba(0, 0, 0, 0) 71%, rgba(121, 121, 229, 0.25) 71%, rgba(79, 79, 221, 0.25) 76%, rgba(0, 0, 0, 0) 76%, rgba(0, 0, 0, 0) 77%, rgba(121, 121, 229, 0.25) 77%, rgba(79, 79, 221, 0.25) 82%, rgba(0, 0, 0, 0) 82%, rgba(0, 0, 0, 0) 83%, rgba(121, 121, 229, 0.25) 83%, rgba(79, 79, 221, 0.25) 88%, rgba(0, 0, 0, 0) 88%, rgba(0, 0, 0, 0) 89%, rgba(121, 121, 229, 0.25) 89%, rgba(79, 79, 221, 0.25) 94%, rgba(0, 0, 0, 0) 94%, rgba(0, 0, 0, 0) 95%, rgba(121, 121, 229, 0.25) 95%, rgba(79, 79, 221, 0.25) 100%, rgba(0, 0, 0, 0) 100%, rgba(0, 0, 0, 0) 100%);
-moz-background-size: 100% 1.5em, auto;
-o-background-size: 100% 1.5em, auto;
-webkit-background-size: 100% 1.5em, auto;
background-size: 100% 1.5em, auto;
background-position: left top; }
.forced-fluid {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuNSIgeDI9IjEuMCIgeTI9IjAuNSI+PHN0b3Agb2Zmc2V0PSIyLjcwMjclIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMi43MDI3JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI4LjEwODExJSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI4LjEwODExJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjEwLjgxMDgxJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjEwLjgxMDgxJSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIxNi4yMTYyMiUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMTYuMjE2MjIlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMTguOTE4OTIlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMTguOTE4OTIlIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjI0LjMyNDMyJSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIyNC4zMjQzMiUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIyNy4wMjcwMyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSIyNy4wMjcwMyUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iMzIuNDMyNDMlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjMyLjQzMjQzJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjM1LjEzNTE0JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjM1LjEzNTE0JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI0MC41NDA1NCUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNDAuNTQwNTQlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNDMuMjQzMjQlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNDMuMjQzMjQlIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjQ4LjY0ODY1JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI0OC42NDg2NSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI1MS4zNTEzNSUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI1MS4zNTEzNSUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNTYuNzU2NzYlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjU2Ljc1Njc2JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjU5LjQ1OTQ2JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjU5LjQ1OTQ2JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI2NC44NjQ4NiUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iNjQuODY0ODYlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNjcuNTY3NTclIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iNjcuNTY3NTclIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjcyLjk3Mjk3JSIgc3RvcC1jb2xvcj0iIzRmNGZkZCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI3Mi45NzI5NyUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI3NS42NzU2OCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wIi8+PHN0b3Agb2Zmc2V0PSI3NS42NzU2OCUiIHN0b3AtY29sb3I9IiM3OTc5ZTUiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iODEuMDgxMDglIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9IjgxLjA4MTA4JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjgzLjc4Mzc4JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjgzLjc4Mzc4JSIgc3RvcC1jb2xvcj0iIzc5NzllNSIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSI4OS4xODkxOSUiIHN0b3AtY29sb3I9IiM0ZjRmZGQiIHN0b3Atb3BhY2l0eT0iMC4yNSIvPjxzdG9wIG9mZnNldD0iODkuMTg5MTklIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iOTEuODkxODklIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iOTEuODkxODklIiBzdG9wLWNvbG9yPSIjNzk3OWU1IiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9Ijk3LjI5NzMlIiBzdG9wLWNvbG9yPSIjNGY0ZmRkIiBzdG9wLW9wYWNpdHk9IjAuMjUiLz48c3RvcCBvZmZzZXQ9Ijk3LjI5NzMlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA=');
background-size: 100%;
background-image: -webkit-gradient(linear, 0% 50%, 100% 50%, color-stop(2.7027%, rgba(0, 0, 0, 0)), color-stop(2.7027%, rgba(121, 121, 229, 0.25)), color-stop(8.10811%, rgba(79, 79, 221, 0.25)), color-stop(8.10811%, rgba(0, 0, 0, 0)), color-stop(10.81081%, rgba(0, 0, 0, 0)), color-stop(10.81081%, rgba(121, 121, 229, 0.25)), color-stop(16.21622%, rgba(79, 79, 221, 0.25)), color-stop(16.21622%, rgba(0, 0, 0, 0)), color-stop(18.91892%, rgba(0, 0, 0, 0)), color-stop(18.91892%, rgba(121, 121, 229, 0.25)), color-stop(24.32432%, rgba(79, 79, 221, 0.25)), color-stop(24.32432%, rgba(0, 0, 0, 0)), color-stop(27.02703%, rgba(0, 0, 0, 0)), color-stop(27.02703%, rgba(121, 121, 229, 0.25)), color-stop(32.43243%, rgba(79, 79, 221, 0.25)), color-stop(32.43243%, rgba(0, 0, 0, 0)), color-stop(35.13514%, rgba(0, 0, 0, 0)), color-stop(35.13514%, rgba(121, 121, 229, 0.25)), color-stop(40.54054%, rgba(79, 79, 221, 0.25)), color-stop(40.54054%, rgba(0, 0, 0, 0)), color-stop(43.24324%, rgba(0, 0, 0, 0)), color-stop(43.24324%, rgba(121, 121, 229, 0.25)), color-stop(48.64865%, rgba(79, 79, 221, 0.25)), color-stop(48.64865%, rgba(0, 0, 0, 0)), color-stop(51.35135%, rgba(0, 0, 0, 0)), color-stop(51.35135%, rgba(121, 121, 229, 0.25)), color-stop(56.75676%, rgba(79, 79, 221, 0.25)), color-stop(56.75676%, rgba(0, 0, 0, 0)), color-stop(59.45946%, rgba(0, 0, 0, 0)), color-stop(59.45946%, rgba(121, 121, 229, 0.25)), color-stop(64.86486%, rgba(79, 79, 221, 0.25)), color-stop(64.86486%, rgba(0, 0, 0, 0)), color-stop(67.56757%, rgba(0, 0, 0, 0)), color-stop(67.56757%, rgba(121, 121, 229, 0.25)), color-stop(72.97297%, rgba(79, 79, 221, 0.25)), color-stop(72.97297%, rgba(0, 0, 0, 0)), color-stop(75.67568%, rgba(0, 0, 0, 0)), color-stop(75.67568%, rgba(121, 121, 229, 0.25)), color-stop(81.08108%, rgba(79, 79, 221, 0.25)), color-stop(81.08108%, rgba(0, 0, 0, 0)), color-stop(83.78378%, rgba(0, 0, 0, 0)), color-stop(83.78378%, rgba(121, 121, 229, 0.25)), color-stop(89.18919%, rgba(79, 79, 221, 0.25)), color-stop(89.18919%, rgba(0, 0, 0, 0)), color-stop(91.89189%, rgba(0, 0, 0, 0)), color-stop(91.89189%, rgba(121, 121, 229, 0.25)), color-stop(97.2973%, rgba(79, 79, 221, 0.25)), color-stop(97.2973%, rgba(0, 0, 0, 0)), color-stop(100%, rgba(0, 0, 0, 0)));
background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0) 2.7027%, rgba(121, 121, 229, 0.25) 2.7027%, rgba(79, 79, 221, 0.25) 8.10811%, rgba(0, 0, 0, 0) 8.10811%, rgba(0, 0, 0, 0) 10.81081%, rgba(121, 121, 229, 0.25) 10.81081%, rgba(79, 79, 221, 0.25) 16.21622%, rgba(0, 0, 0, 0) 16.21622%, rgba(0, 0, 0, 0) 18.91892%, rgba(121, 121, 229, 0.25) 18.91892%, rgba(79, 79, 221, 0.25) 24.32432%, rgba(0, 0, 0, 0) 24.32432%, rgba(0, 0, 0, 0) 27.02703%, rgba(121, 121, 229, 0.25) 27.02703%, rgba(79, 79, 221, 0.25) 32.43243%, rgba(0, 0, 0, 0) 32.43243%, rgba(0, 0, 0, 0) 35.13514%, rgba(121, 121, 229, 0.25) 35.13514%, rgba(79, 79, 221, 0.25) 40.54054%, rgba(0, 0, 0, 0) 40.54054%, rgba(0, 0, 0, 0) 43.24324%, rgba(121, 121, 229, 0.25) 43.24324%, rgba(79, 79, 221, 0.25) 48.64865%, rgba(0, 0, 0, 0) 48.64865%, rgba(0, 0, 0, 0) 51.35135%, rgba(121, 121, 229, 0.25) 51.35135%, rgba(79, 79, 221, 0.25) 56.75676%, rgba(0, 0, 0, 0) 56.75676%, rgba(0, 0, 0, 0) 59.45946%, rgba(121, 121, 229, 0.25) 59.45946%, rgba(79, 79, 221, 0.25) 64.86486%, rgba(0, 0, 0, 0) 64.86486%, rgba(0, 0, 0, 0) 67.56757%, rgba(121, 121, 229, 0.25) 67.56757%, rgba(79, 79, 221, 0.25) 72.97297%, rgba(0, 0, 0, 0) 72.97297%, rgba(0, 0, 0, 0) 75.67568%, rgba(121, 121, 229, 0.25) 75.67568%, rgba(79, 79, 221, 0.25) 81.08108%, rgba(0, 0, 0, 0) 81.08108%, rgba(0, 0, 0, 0) 83.78378%, rgba(121, 121, 229, 0.25) 83.78378%, rgba(79, 79, 221, 0.25) 89.18919%, rgba(0, 0, 0, 0) 89.18919%, rgba(0, 0, 0, 0) 91.89189%, rgba(121, 121, 229, 0.25) 91.89189%, rgba(79, 79, 221, 0.25) 97.2973%, rgba(0, 0, 0, 0) 97.2973%, rgba(0, 0, 0, 0) 100%);
background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0) 2.7027%, rgba(121, 121, 229, 0.25) 2.7027%, rgba(79, 79, 221, 0.25) 8.10811%, rgba(0, 0, 0, 0) 8.10811%, rgba(0, 0, 0, 0) 10.81081%, rgba(121, 121, 229, 0.25) 10.81081%, rgba(79, 79, 221, 0.25) 16.21622%, rgba(0, 0, 0, 0) 16.21622%, rgba(0, 0, 0, 0) 18.91892%, rgba(121, 121, 229, 0.25) 18.91892%, rgba(79, 79, 221, 0.25) 24.32432%, rgba(0, 0, 0, 0) 24.32432%, rgba(0, 0, 0, 0) 27.02703%, rgba(121, 121, 229, 0.25) 27.02703%, rgba(79, 79, 221, 0.25) 32.43243%, rgba(0, 0, 0, 0) 32.43243%, rgba(0, 0, 0, 0) 35.13514%, rgba(121, 121, 229, 0.25) 35.13514%, rgba(79, 79, 221, 0.25) 40.54054%, rgba(0, 0, 0, 0) 40.54054%, rgba(0, 0, 0, 0) 43.24324%, rgba(121, 121, 229, 0.25) 43.24324%, rgba(79, 79, 221, 0.25) 48.64865%, rgba(0, 0, 0, 0) 48.64865%, rgba(0, 0, 0, 0) 51.35135%, rgba(121, 121, 229, 0.25) 51.35135%, rgba(79, 79, 221, 0.25) 56.75676%, rgba(0, 0, 0, 0) 56.75676%, rgba(0, 0, 0, 0) 59.45946%, rgba(121, 121, 229, 0.25) 59.45946%, rgba(79, 79, 221, 0.25) 64.86486%, rgba(0, 0, 0, 0) 64.86486%, rgba(0, 0, 0, 0) 67.56757%, rgba(121, 121, 229, 0.25) 67.56757%, rgba(79, 79, 221, 0.25) 72.97297%, rgba(0, 0, 0, 0) 72.97297%, rgba(0, 0, 0, 0) 75.67568%, rgba(121, 121, 229, 0.25) 75.67568%, rgba(79, 79, 221, 0.25) 81.08108%, rgba(0, 0, 0, 0) 81.08108%, rgba(0, 0, 0, 0) 83.78378%, rgba(121, 121, 229, 0.25) 83.78378%, rgba(79, 79, 221, 0.25) 89.18919%, rgba(0, 0, 0, 0) 89.18919%, rgba(0, 0, 0, 0) 91.89189%, rgba(121, 121, 229, 0.25) 91.89189%, rgba(79, 79, 221, 0.25) 97.2973%, rgba(0, 0, 0, 0) 97.2973%, rgba(0, 0, 0, 0) 100%);
background-image: linear-gradient(to right, rgba(0, 0, 0, 0) 2.7027%, rgba(121, 121, 229, 0.25) 2.7027%, rgba(79, 79, 221, 0.25) 8.10811%, rgba(0, 0, 0, 0) 8.10811%, rgba(0, 0, 0, 0) 10.81081%, rgba(121, 121, 229, 0.25) 10.81081%, rgba(79, 79, 221, 0.25) 16.21622%, rgba(0, 0, 0, 0) 16.21622%, rgba(0, 0, 0, 0) 18.91892%, rgba(121, 121, 229, 0.25) 18.91892%, rgba(79, 79, 221, 0.25) 24.32432%, rgba(0, 0, 0, 0) 24.32432%, rgba(0, 0, 0, 0) 27.02703%, rgba(121, 121, 229, 0.25) 27.02703%, rgba(79, 79, 221, 0.25) 32.43243%, rgba(0, 0, 0, 0) 32.43243%, rgba(0, 0, 0, 0) 35.13514%, rgba(121, 121, 229, 0.25) 35.13514%, rgba(79, 79, 221, 0.25) 40.54054%, rgba(0, 0, 0, 0) 40.54054%, rgba(0, 0, 0, 0) 43.24324%, rgba(121, 121, 229, 0.25) 43.24324%, rgba(79, 79, 221, 0.25) 48.64865%, rgba(0, 0, 0, 0) 48.64865%, rgba(0, 0, 0, 0) 51.35135%, rgba(121, 121, 229, 0.25) 51.35135%, rgba(79, 79, 221, 0.25) 56.75676%, rgba(0, 0, 0, 0) 56.75676%, rgba(0, 0, 0, 0) 59.45946%, rgba(121, 121, 229, 0.25) 59.45946%, rgba(79, 79, 221, 0.25) 64.86486%, rgba(0, 0, 0, 0) 64.86486%, rgba(0, 0, 0, 0) 67.56757%, rgba(121, 121, 229, 0.25) 67.56757%, rgba(79, 79, 221, 0.25) 72.97297%, rgba(0, 0, 0, 0) 72.97297%, rgba(0, 0, 0, 0) 75.67568%, rgba(121, 121, 229, 0.25) 75.67568%, rgba(79, 79, 221, 0.25) 81.08108%, rgba(0, 0, 0, 0) 81.08108%, rgba(0, 0, 0, 0) 83.78378%, rgba(121, 121, 229, 0.25) 83.78378%, rgba(79, 79, 221, 0.25) 89.18919%, rgba(0, 0, 0, 0) 89.18919%, rgba(0, 0, 0, 0) 91.89189%, rgba(121, 121, 229, 0.25) 91.89189%, rgba(79, 79, 221, 0.25) 97.2973%, rgba(0, 0, 0, 0) 97.2973%, rgba(0, 0, 0, 0) 100%);
background-position: left top; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/hyphenation.css
================================================
.word-break {
word-break: keep-all; }
.hyphens {
-moz-hyphens: manual;
-ms-hyphens: manual;
-webkit-hyphens: manual;
hyphens: manual; }
.hyphenate {
word-break: break-all;
word-break: break-word;
-moz-hyphens: auto;
-ms-hyphens: auto;
-webkit-hyphens: auto;
hyphens: auto; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/image_size.css
================================================
.png {
width: 100px;
height: 150px; }
.jpg {
width: 100px;
height: 150px; }
.jpeg {
width: 100px;
height: 150px; }
.gif {
width: 100px;
height: 150px; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/images.css
================================================
.relative {
background-image: url('/images/4x6.png?busted=true'); }
.root-relative {
background-image: url('/images/4x6.png?busted=true'); }
.absolute {
background-image: url(http://example.com/images/4x6.png); }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/layout.css
================================================
html, body {
height: 100%; }
#layout {
clear: both;
min-height: 100%;
height: auto !important;
height: 100%;
margin-bottom: -72px; }
#layout #layout_footer {
height: 72px; }
#footer {
clear: both;
position: relative;
height: 72px; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/legacy_clearfix.css
================================================
.clearfix {
overflow: hidden;
display: inline-block; }
.clearfix {
display: block; }
.pie-clearfix {
display: inline-block; }
.pie-clearfix:after {
content: "\0020";
display: block;
height: 0;
clear: both;
overflow: hidden;
visibility: hidden; }
.pie-clearfix {
display: block; }
.simplified-pie-clearfix {
display: inline-block; }
.simplified-pie-clearfix:after {
content: "";
display: table;
clear: both; }
.simplified-pie-clearfix {
display: block; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/lists.css
================================================
ul.horizontal {
margin: 0;
padding: 0;
border: 0;
overflow: hidden;
*zoom: 1; }
ul.horizontal li {
list-style-image: none;
list-style-type: none;
margin-left: 0;
white-space: nowrap;
float: left;
padding-left: 4px;
padding-right: 4px; }
ul.horizontal li:first-child {
padding-left: 0; }
ul.horizontal li:last-child {
padding-right: 0; }
ul.horizontal li.last {
padding-right: 0; }
ul.wide-horizontal {
margin: 0;
padding: 0;
border: 0;
overflow: hidden;
*zoom: 1; }
ul.wide-horizontal li {
list-style-image: none;
list-style-type: none;
margin-left: 0;
white-space: nowrap;
float: left;
padding-left: 10px;
padding-right: 10px; }
ul.wide-horizontal li:first-child {
padding-left: 0; }
ul.wide-horizontal li:last-child {
padding-right: 0; }
ul.wide-horizontal li.last {
padding-right: 0; }
ul.right-horizontal {
margin: 0;
padding: 0;
border: 0;
overflow: hidden;
*zoom: 1; }
ul.right-horizontal li {
list-style-image: none;
list-style-type: none;
margin-left: 0;
white-space: nowrap;
float: right;
padding-left: 4px;
padding-right: 4px; }
ul.right-horizontal li:first-child {
padding-right: 0; }
ul.right-horizontal li:last-child {
padding-left: 0; }
ul.right-horizontal li.last {
padding-left: 0; }
ul.no-padding {
margin: 0;
padding: 0;
border: 0;
overflow: hidden;
*zoom: 1; }
ul.no-padding li {
list-style-image: none;
list-style-type: none;
margin-left: 0;
white-space: nowrap;
float: left; }
ul.inline-block {
margin: 0;
padding: 0;
border: 0;
overflow: hidden;
*zoom: 1; }
ul.inline-block li {
list-style-image: none;
list-style-type: none;
margin-left: 0;
display: inline-block;
vertical-align: middle;
*vertical-align: auto;
*zoom: 1;
*display: inline;
white-space: nowrap; }
ul.wide-inline-block {
margin: 0;
padding: 0;
border: 0;
overflow: hidden;
*zoom: 1; }
ul.wide-inline-block li {
list-style-image: none;
list-style-type: none;
margin-left: 0;
display: inline-block;
vertical-align: middle;
*vertical-align: auto;
*zoom: 1;
*display: inline;
white-space: nowrap;
padding-left: 10px;
padding-right: 10px; }
ul.inline {
list-style-type: none; }
ul.inline, ul.inline li {
margin: 0;
padding: 0;
display: inline; }
ul.comma {
list-style-type: none; }
ul.comma, ul.comma li {
margin: 0;
padding: 0;
display: inline; }
ul.comma li:after {
content: ", "; }
ul.comma li:last-child:after {
content: ""; }
ul.comma li.last:after {
content: ""; }
ul.no-bullets {
list-style: none; }
ul.no-bullets li {
list-style-image: none;
list-style-type: none;
margin-left: 0; }
ul.pretty {
margin-left: 0; }
ul.pretty li {
padding-left: 14px;
background: url('/images/4x6.png?busted=true') no-repeat 4px 7px;
list-style-type: none; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/opacity.css
================================================
div {
filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false);
opacity: 1; }
div {
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=20);
opacity: 0.2; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/print.css
================================================
.noprint, .no-print {
display: none; }
address.print-only, article.print-only, aside.print-only, blockquote.print-only, center.print-only, dir.print-only, div.print-only, dd.print-only, details.print-only, dl.print-only, dt.print-only, fieldset.print-only, figcaption.print-only, figure.print-only, form.print-only, footer.print-only, frameset.print-only, h1.print-only, h2.print-only, h3.print-only, h4.print-only, h5.print-only, h6.print-only, hr.print-only, header.print-only, hgroup.print-only, isindex.print-only, main.print-only, menu.print-only, nav.print-only, noframes.print-only, noscript.print-only, ol.print-only, p.print-only, pre.print-only, section.print-only, summary.print-only, ul.print-only {
display: block; }
a.print-only, abbr.print-only, acronym.print-only, audio.print-only, b.print-only, basefont.print-only, bdo.print-only, big.print-only, br.print-only, canvas.print-only, cite.print-only, code.print-only, command.print-only, datalist.print-only, dfn.print-only, em.print-only, embed.print-only, font.print-only, i.print-only, img.print-only, input.print-only, keygen.print-only, kbd.print-only, label.print-only, mark.print-only, meter.print-only, output.print-only, progress.print-only, q.print-only, rp.print-only, rt.print-only, ruby.print-only, s.print-only, samp.print-only, select.print-only, small.print-only, span.print-only, strike.print-only, strong.print-only, sub.print-only, sup.print-only, textarea.print-only, time.print-only, tt.print-only, u.print-only, var.print-only, video.print-only, wbr.print-only {
display: inline; }
.print-only {
display: none; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/regions.css
================================================
.source {
-ms-flow-into: target;
-webkit-flow-into: target;
flow-into: target; }
.new-container {
-ms-flow-from: target;
-webkit-flow-from: target;
flow-from: target; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/replacement.css
================================================
.basic {
text-indent: -119988px;
overflow: hidden;
text-align: left;
text-transform: capitalize;
background-image: url('/images/4x6.png?busted=true');
background-repeat: no-repeat;
background-position: 50% 50%; }
.with-dimensions {
text-indent: -119988px;
overflow: hidden;
text-align: left;
text-transform: capitalize;
background-image: url('/images/4x6.png?busted=true');
background-repeat: no-repeat;
background-position: 50% 50%;
width: 6px;
height: 4px; }
.with-dimensions-inline {
text-indent: -119988px;
overflow: hidden;
text-align: left;
text-transform: capitalize;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAIAAAAiZtkUAAAC7mlDQ1BJQ0MgUHJvZmlsZQAAeAGFVM9rE0EU/jZuqdAiCFprDrJ4kCJJWatoRdQ2/RFiawzbH7ZFkGQzSdZuNuvuJrWliOTi0SreRe2hB/+AHnrwZC9KhVpFKN6rKGKhFy3xzW5MtqXqwM5+8943731vdt8ADXLSNPWABOQNx1KiEWlsfEJq/IgAjqIJQTQlVdvsTiQGQYNz+Xvn2HoPgVtWw3v7d7J3rZrStpoHhP1A4Eea2Sqw7xdxClkSAog836Epx3QI3+PY8uyPOU55eMG1Dys9xFkifEA1Lc5/TbhTzSXTQINIOJT1cVI+nNeLlNcdB2luZsbIEL1PkKa7zO6rYqGcTvYOkL2d9H5Os94+wiHCCxmtP0a4jZ71jNU/4mHhpObEhj0cGDX0+GAVtxqp+DXCFF8QTSeiVHHZLg3xmK79VvJKgnCQOMpkYYBzWkhP10xu+LqHBX0m1xOv4ndWUeF5jxNn3tTd70XaAq8wDh0MGgyaDUhQEEUEYZiwUECGPBoxNLJyPyOrBhuTezJ1JGq7dGJEsUF7Ntw9t1Gk3Tz+KCJxlEO1CJL8Qf4qr8lP5Xn5y1yw2Fb3lK2bmrry4DvF5Zm5Gh7X08jjc01efJXUdpNXR5aseXq8muwaP+xXlzHmgjWPxHOw+/EtX5XMlymMFMXjVfPqS4R1WjE3359sfzs94i7PLrXWc62JizdWm5dn/WpI++6qvJPmVflPXvXx/GfNxGPiKTEmdornIYmXxS7xkthLqwviYG3HCJ2VhinSbZH6JNVgYJq89S9dP1t4vUZ/DPVRlBnM0lSJ93/CKmQ0nbkOb/qP28f8F+T3iuefKAIvbODImbptU3HvEKFlpW5zrgIXv9F98LZua6N+OPwEWDyrFq1SNZ8gvAEcdod6HugpmNOWls05Uocsn5O66cpiUsxQ20NSUtcl12VLFrOZVWLpdtiZ0x1uHKE5QvfEp0plk/qv8RGw/bBS+fmsUtl+ThrWgZf6b8C8/UXAeIuJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAI0lEQVQIHWOwtLT8//9/eno6kISwGdD4QDkGZHkIG6QKTS8A/s4vHesO+KkAAAAASUVORK5CYII=');
background-repeat: no-repeat;
background-position: 50% 50%;
width: 6px;
height: 4px; }
.with-position {
text-indent: -119988px;
overflow: hidden;
text-align: left;
text-transform: capitalize;
background-image: url('/images/4x6.png?busted=true');
background-repeat: no-repeat;
background-position: 10px top; }
.with-arbitrary-url {
text-indent: -119988px;
overflow: hidden;
text-align: left;
text-transform: capitalize;
background-image: url(http://google.com/logo.gif);
background-repeat: no-repeat;
background-position: 10px top; }
.with-inline-url {
text-indent: -119988px;
overflow: hidden;
text-align: left;
text-transform: capitalize;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAIAAAAiZtkUAAAC7mlDQ1BJQ0MgUHJvZmlsZQAAeAGFVM9rE0EU/jZuqdAiCFprDrJ4kCJJWatoRdQ2/RFiawzbH7ZFkGQzSdZuNuvuJrWliOTi0SreRe2hB/+AHnrwZC9KhVpFKN6rKGKhFy3xzW5MtqXqwM5+8943731vdt8ADXLSNPWABOQNx1KiEWlsfEJq/IgAjqIJQTQlVdvsTiQGQYNz+Xvn2HoPgVtWw3v7d7J3rZrStpoHhP1A4Eea2Sqw7xdxClkSAog836Epx3QI3+PY8uyPOU55eMG1Dys9xFkifEA1Lc5/TbhTzSXTQINIOJT1cVI+nNeLlNcdB2luZsbIEL1PkKa7zO6rYqGcTvYOkL2d9H5Os94+wiHCCxmtP0a4jZ71jNU/4mHhpObEhj0cGDX0+GAVtxqp+DXCFF8QTSeiVHHZLg3xmK79VvJKgnCQOMpkYYBzWkhP10xu+LqHBX0m1xOv4ndWUeF5jxNn3tTd70XaAq8wDh0MGgyaDUhQEEUEYZiwUECGPBoxNLJyPyOrBhuTezJ1JGq7dGJEsUF7Ntw9t1Gk3Tz+KCJxlEO1CJL8Qf4qr8lP5Xn5y1yw2Fb3lK2bmrry4DvF5Zm5Gh7X08jjc01efJXUdpNXR5aseXq8muwaP+xXlzHmgjWPxHOw+/EtX5XMlymMFMXjVfPqS4R1WjE3359sfzs94i7PLrXWc62JizdWm5dn/WpI++6qvJPmVflPXvXx/GfNxGPiKTEmdornIYmXxS7xkthLqwviYG3HCJ2VhinSbZH6JNVgYJq89S9dP1t4vUZ/DPVRlBnM0lSJ93/CKmQ0nbkOb/qP28f8F+T3iuefKAIvbODImbptU3HvEKFlpW5zrgIXv9F98LZua6N+OPwEWDyrFq1SNZ8gvAEcdod6HugpmNOWls05Uocsn5O66cpiUsxQ20NSUtcl12VLFrOZVWLpdtiZ0x1uHKE5QvfEp0plk/qv8RGw/bBS+fmsUtl+ThrWgZf6b8C8/UXAeIuJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAI0lEQVQIHWOwtLT8//9/eno6kISwGdD4QDkGZHkIG6QKTS8A/s4vHesO+KkAAAAASUVORK5CYII=');
background-repeat: no-repeat;
background-position: 10px top; }
.with-image-url {
text-indent: -119988px;
overflow: hidden;
text-align: left;
text-transform: capitalize;
background-image: url('/images/4x6.png?busted=true');
background-repeat: no-repeat;
background-position: 10px top; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/reset.css
================================================
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font: inherit;
font-size: 100%;
vertical-align: baseline; }
html {
line-height: 1; }
ol, ul {
list-style: none; }
table {
border-collapse: collapse;
border-spacing: 0; }
caption, th, td {
text-align: left;
font-weight: normal;
vertical-align: middle; }
q, blockquote {
quotes: none; }
q:before, q:after, blockquote:before, blockquote:after {
content: "";
content: none; }
a img {
border: none; }
article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section, summary {
display: block; }
.unregistered-only, .registered-only {
display: none; }
body.registered a.registered-only, body.registered abbr.registered-only, body.registered acronym.registered-only, body.registered audio.registered-only, body.registered b.registered-only, body.registered basefont.registered-only, body.registered bdo.registered-only, body.registered big.registered-only, body.registered br.registered-only, body.registered canvas.registered-only, body.registered cite.registered-only, body.registered code.registered-only, body.registered command.registered-only, body.registered datalist.registered-only, body.registered dfn.registered-only, body.registered em.registered-only, body.registered embed.registered-only, body.registered font.registered-only, body.registered i.registered-only, body.registered img.registered-only, body.registered input.registered-only, body.registered keygen.registered-only, body.registered kbd.registered-only, body.registered label.registered-only, body.registered mark.registered-only, body.registered meter.registered-only, body.registered output.registered-only, body.registered progress.registered-only, body.registered q.registered-only, body.registered rp.registered-only, body.registered rt.registered-only, body.registered ruby.registered-only, body.registered s.registered-only, body.registered samp.registered-only, body.registered select.registered-only, body.registered small.registered-only, body.registered span.registered-only, body.registered strike.registered-only, body.registered strong.registered-only, body.registered sub.registered-only, body.registered sup.registered-only, body.registered textarea.registered-only, body.registered time.registered-only, body.registered tt.registered-only, body.registered u.registered-only, body.registered var.registered-only, body.registered video.registered-only, body.registered wbr.registered-only {
display: inline; }
body.registered address.registered-only, body.registered article.registered-only, body.registered aside.registered-only, body.registered blockquote.registered-only, body.registered center.registered-only, body.registered dir.registered-only, body.registered div.registered-only, body.registered dd.registered-only, body.registered details.registered-only, body.registered dl.registered-only, body.registered dt.registered-only, body.registered fieldset.registered-only, body.registered figcaption.registered-only, body.registered figure.registered-only, body.registered form.registered-only, body.registered footer.registered-only, body.registered frameset.registered-only, body.registered h1.registered-only, body.registered h2.registered-only, body.registered h3.registered-only, body.registered h4.registered-only, body.registered h5.registered-only, body.registered h6.registered-only, body.registered hr.registered-only, body.registered header.registered-only, body.registered hgroup.registered-only, body.registered isindex.registered-only, body.registered main.registered-only, body.registered menu.registered-only, body.registered nav.registered-only, body.registered noframes.registered-only, body.registered noscript.registered-only, body.registered ol.registered-only, body.registered p.registered-only, body.registered pre.registered-only, body.registered section.registered-only, body.registered summary.registered-only, body.registered ul.registered-only {
display: block; }
body.unregistered a.unregistered-only, body.unregistered abbr.unregistered-only, body.unregistered acronym.unregistered-only, body.unregistered audio.unregistered-only, body.unregistered b.unregistered-only, body.unregistered basefont.unregistered-only, body.unregistered bdo.unregistered-only, body.unregistered big.unregistered-only, body.unregistered br.unregistered-only, body.unregistered canvas.unregistered-only, body.unregistered cite.unregistered-only, body.unregistered code.unregistered-only, body.unregistered command.unregistered-only, body.unregistered datalist.unregistered-only, body.unregistered dfn.unregistered-only, body.unregistered em.unregistered-only, body.unregistered embed.unregistered-only, body.unregistered font.unregistered-only, body.unregistered i.unregistered-only, body.unregistered img.unregistered-only, body.unregistered input.unregistered-only, body.unregistered keygen.unregistered-only, body.unregistered kbd.unregistered-only, body.unregistered label.unregistered-only, body.unregistered mark.unregistered-only, body.unregistered meter.unregistered-only, body.unregistered output.unregistered-only, body.unregistered progress.unregistered-only, body.unregistered q.unregistered-only, body.unregistered rp.unregistered-only, body.unregistered rt.unregistered-only, body.unregistered ruby.unregistered-only, body.unregistered s.unregistered-only, body.unregistered samp.unregistered-only, body.unregistered select.unregistered-only, body.unregistered small.unregistered-only, body.unregistered span.unregistered-only, body.unregistered strike.unregistered-only, body.unregistered strong.unregistered-only, body.unregistered sub.unregistered-only, body.unregistered sup.unregistered-only, body.unregistered textarea.unregistered-only, body.unregistered time.unregistered-only, body.unregistered tt.unregistered-only, body.unregistered u.unregistered-only, body.unregistered var.unregistered-only, body.unregistered video.unregistered-only, body.unregistered wbr.unregistered-only {
display: inline; }
body.unregistered address.unregistered-only, body.unregistered article.unregistered-only, body.unregistered aside.unregistered-only, body.unregistered blockquote.unregistered-only, body.unregistered center.unregistered-only, body.unregistered dir.unregistered-only, body.unregistered div.unregistered-only, body.unregistered dd.unregistered-only, body.unregistered details.unregistered-only, body.unregistered dl.unregistered-only, body.unregistered dt.unregistered-only, body.unregistered fieldset.unregistered-only, body.unregistered figcaption.unregistered-only, body.unregistered figure.unregistered-only, body.unregistered form.unregistered-only, body.unregistered footer.unregistered-only, body.unregistered frameset.unregistered-only, body.unregistered h1.unregistered-only, body.unregistered h2.unregistered-only, body.unregistered h3.unregistered-only, body.unregistered h4.unregistered-only, body.unregistered h5.unregistered-only, body.unregistered h6.unregistered-only, body.unregistered hr.unregistered-only, body.unregistered header.unregistered-only, body.unregistered hgroup.unregistered-only, body.unregistered isindex.unregistered-only, body.unregistered main.unregistered-only, body.unregistered menu.unregistered-only, body.unregistered nav.unregistered-only, body.unregistered noframes.unregistered-only, body.unregistered noscript.unregistered-only, body.unregistered ol.unregistered-only, body.unregistered p.unregistered-only, body.unregistered pre.unregistered-only, body.unregistered section.unregistered-only, body.unregistered summary.unregistered-only, body.unregistered ul.unregistered-only {
display: block; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/selection.css
================================================
*::-moz-selection {
background-color: #fe57a1;
color: #fff; }
*::selection {
background-color: #fe57a1;
color: #fff; }
.hot-pink::-moz-selection {
background-color: #fe57a1;
color: #fff; }
.hot-pink::selection {
background-color: #fe57a1;
color: #fff; }
.hot-pink-with-arguments::-moz-selection {
color: white;
background-color: #fe57a1; }
.hot-pink-with-arguments::selection {
color: white;
background-color: #fe57a1; }
.hot-pink-with-arguments-and-extra-stuff::-moz-selection {
color: white;
background-color: #fe57a1;
text-decoration: line-through; }
.hot-pink-with-arguments-and-extra-stuff::selection {
color: white;
background-color: #fe57a1;
text-decoration: line-through; }
.hot-pink-with-default-foreground::-moz-selection {
color: black;
background-color: #fe57a1; }
.hot-pink-with-default-foreground::selection {
color: black;
background-color: #fe57a1; }
.browser-support-is-considered::-moz-selection {
color: black;
background-color: #fe57a1;
prefix: -moz;
-moz-prefix: true;
-ms-prefix: false;
-webkit-prefix: false; }
.browser-support-is-considered::selection {
color: black;
background-color: #fe57a1;
-moz-prefix: false;
-ms-prefix: false;
-webkit-prefix: false; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/sprites_with_explicit_separator.css
================================================
.flag_states_sprite, .flag_states_foo {
background-image: url('/images/flag_states-sc42d7bf926.png');
background-repeat: no-repeat; }
.flag_states_foo {
background-position: 0 0;
height: 11px;
width: 16px; }
.flag_states_foo:hover, .flag_states_foo.foo_hover {
background-position: 0 -33px; }
.flag_states_foo:target, .flag_states_foo.foo_target {
background-position: 0 -44px; }
.flag_states_foo:active, .flag_states_foo.foo_active {
background-position: 0 -11px; }
.flag_states_foo:focus, .flag_states_foo.foo_focus {
background-position: 0 -22px; }
.sprite-file {
location: url('/images/flag_states/foo.png?busted=true'); }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/stretching.css
================================================
.stretched-completely {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0; }
.stretched-horizontally {
position: absolute;
left: 0;
right: 0; }
.stretched-right {
position: absolute;
left: 0;
right: 50%; }
.left-pane {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 50%; }
.stretched-left {
position: absolute;
left: 50%;
right: 0; }
.right-pane {
position: absolute;
top: 0;
bottom: 0;
left: 50%;
right: 0; }
.stretched-down {
position: absolute;
top: 0;
bottom: 50%; }
.top-pane {
position: absolute;
top: 0;
bottom: 50%;
left: 0;
right: 0; }
.stretched-up {
position: absolute;
top: 50%;
bottom: 0; }
.bottom-pane {
position: absolute;
top: 50%;
bottom: 0;
left: 0;
right: 0; }
.viewport {
position: absolute;
top: 10px;
bottom: 30px;
left: 40px;
right: 20px; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/support.css
================================================
/* ### Compass Support ---------- */
/* - [function] set-arglist-default() with no arguments (1 Assertions, 1 Passed, 0 Failed) */
/* - [function] set-arglist-default() with a "default" argument (1 Assertions, 1 Passed, 0 Failed) */
/* - [function] set-arglist-default() with a "default" argument and another argument (1 Assertions, 1 Passed, 0 Failed) */
/* - [function] set-arglist-default() with a "default" argument not first and another argument (1 Assertions, 1 Passed, 0 Failed) */
/* - [function] support-legacy-browser() from threshold (2 Assertions, 2 Passed, 0 Failed) */
/* - [function] support-legacy-browser() from minimums (2 Assertions, 2 Passed, 0 Failed) */
/* - [function] browser-out-of-scope() with no scope (2 Assertions, 2 Passed, 0 Failed) */
/* - prefix context tracking (9 Assertions, 9 Passed, 0 Failed) */
/* - [function] browser-out-of-scope() with a scope (2 Assertions, 2 Passed, 0 Failed) */
/* - [function] browser-out-of-scope() with version (3 Assertions, 3 Passed, 0 Failed) */
/* - [mixin] with-prefix() (4 Assertions, 4 Passed, 0 Failed) */
/* - [mixin] with-each-prefix() (1 Assertions, 1 Passed, 0 Failed) */
/* - [mixin] with-each-prefix() respects $supported-browsers (1 Assertions, 1 Passed, 0 Failed) */
/* - [mixin] with-each-prefix() respects $current-prefix (3 Assertions, 3 Passed, 0 Failed) */
/* - [fuction] has-browser-subset() (5 Assertions, 5 Passed, 0 Failed) */
/*
*/
/* 15 Tests: */
/* - 15 Passed */
/* - 0 Failed */
/*
*/
/* Capability css-animation is prefixed with -moz because 0.57224% of users need it which is more than the threshold of 0.1%. */
/* Creating new -moz context. */
@-moz-keyframes foo {
0% {
/* Content for ie 8 omitted.
Not allowed in the current scope: ie 8 is incompatible with -moz. */
opacity: 0; }
100% {
/* Content for ie 8 omitted.
Not allowed in the current scope: ie 8 is incompatible with -moz. */
opacity: 1; } }
/* Capability css-animation is not prefixed with -ms because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-animation is not prefixed with -o because 0.02146% of users are affected which is less than the threshold of 0.1. */
/* Capability css-animation is prefixed with -webkit because 57.87258% of users need it which is more than the threshold of 0.1%. */
/* Creating new -webkit context. */
@-webkit-keyframes foo {
0% {
/* Content for ie 8 omitted.
Not allowed in the current scope: ie 8 is incompatible with -webkit. */
opacity: 0; }
100% {
/* Content for ie 8 omitted.
Not allowed in the current scope: ie 8 is incompatible with -webkit. */
opacity: 1; } }
@keyframes foo {
0% {
/* Content for ie 8 omitted.
Not allowed in the current scope: The current scope only works with ie 10 - 11. */
opacity: 0; }
100% {
/* Content for ie 8 omitted.
Not allowed in the current scope: The current scope only works with ie 10 - 11. */
opacity: 1; } }
.foo {
/* Capability css-animation is prefixed with -moz because 0.57224% of users need it which is more than the threshold of 0.1%. */
/* Creating new -moz context. */
-moz-animation: foo 1s;
/* Capability css-animation is not prefixed with -ms because 0% of users are affected which is less than the threshold of 0.1. */
/* Capability css-animation is not prefixed with -o because 0.02146% of users are affected which is less than the threshold of 0.1. */
/* Capability css-animation is prefixed with -webkit because 57.87258% of users need it which is more than the threshold of 0.1%. */
/* Creating new -webkit context. */
-webkit-animation: foo 1s;
animation: foo 1s; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/text_shadow.css
================================================
.default-single-text-shadow {
text-shadow: 0px 0px 1px #aaaaaa; }
.none {
text-shadow: none; }
.color-only {
text-shadow: 0px 0px 1px #cccccc; }
.color-first-with-params {
text-shadow: 2px 2px 5px #cccccc;
text-shadow: 2px 2px 5px 2px #cccccc; }
.color-last-with-params {
text-shadow: 2px 2px 5px #cccccc;
text-shadow: 2px 2px 5px 2px #cccccc; }
.default-text-shadow {
text-shadow: 0px 0px 1px #aaaaaa; }
.multiple-text-shadows-with-default {
text-shadow: 0px 0px 1px #aaaaaa, 2px 2px 5px #222222; }
.multiple-text-shadows {
text-shadow: 4px 4px 10px #444444, 2px 2px 5px #222222; }
.multiple-text-shadows-with-spread {
text-shadow: 4px 4px 10px #444444, 2px 2px 5px #222222;
text-shadow: 4px 4px 10px 1px #444444, 2px 2px 5px 3px #222222; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/transform.css
================================================
.apply-origin-2d {
-moz-transform-origin: 2px 5%;
-ms-transform-origin: 2px 5%;
-webkit-transform-origin: 2px 5%;
transform-origin: 2px 5%; }
.apply-origin-3d {
-moz-transform-origin: 2px 5% 2in;
-webkit-transform-origin: 2px 5% 2in;
transform-origin: 2px 5% 2in; }
.transform-origin-2d {
-moz-transform-origin: 100px 100px;
-ms-transform-origin: 100px 100px;
-webkit-transform-origin: 100px 100px;
transform-origin: 100px 100px; }
.transform-origin-3d {
-moz-transform-origin: 100px 100px 100px;
-webkit-transform-origin: 100px 100px 100px;
transform-origin: 100px 100px 100px; }
.transform-2d {
-moz-transform: rotateY(20deg);
-ms-transform: rotateY(20deg);
-webkit-transform: rotateY(20deg);
transform: rotateY(20deg); }
.transform-3d {
-moz-transform: rotateZ(20deg);
-webkit-transform: rotateZ(20deg);
transform: rotateZ(20deg); }
.perspective {
-moz-perspective: 500;
-webkit-perspective: 500;
perspective: 500; }
.perspective-origin {
-moz-perspective-origin: 25% 25%;
-webkit-perspective-origin: 25% 25%;
perspective-origin: 25% 25%; }
.transform-style {
-moz-transform-style: preserve-3d;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d; }
.backface-visibility {
-moz-backface-visibility: hidden;
-webkit-backface-visibility: hidden;
backface-visibility: hidden; }
.scale {
-moz-transform: scale(30px, 50px);
-ms-transform: scale(30px, 50px);
-webkit-transform: scale(30px, 50px);
transform: scale(30px, 50px); }
.scale-3d {
-moz-transform: scale(30px, 50px);
-webkit-transform: scale(30px, 50px);
transform: scale(30px, 50px); }
.scale-with-perspective {
-moz-transform: perspective(500) scale(30px, 50px);
-ms-transform: perspective(500) scale(30px, 50px);
-webkit-transform: perspective(500) scale(30px, 50px);
transform: perspective(500) scale(30px, 50px); }
.scale-3d-with-perspective {
-moz-transform: perspective(500) scale(30px, 50px);
-webkit-transform: perspective(500) scale(30px, 50px);
transform: perspective(500) scale(30px, 50px); }
.scale-x {
-moz-transform: scaleX(30px);
-ms-transform: scaleX(30px);
-webkit-transform: scaleX(30px);
transform: scaleX(30px); }
.scale-x-3d {
-moz-transform: scaleX(30px);
-webkit-transform: scaleX(30px);
transform: scaleX(30px); }
.scale-x-with-perspective {
-moz-transform: perspective(500) scaleX(30px);
-ms-transform: perspective(500) scaleX(30px);
-webkit-transform: perspective(500) scaleX(30px);
transform: perspective(500) scaleX(30px); }
.scale-x-3d-with-perspective {
-moz-transform: perspective(500) scaleX(30px);
-webkit-transform: perspective(500) scaleX(30px);
transform: perspective(500) scaleX(30px); }
.scale-y {
-moz-transform: scaleY(50px);
-ms-transform: scaleY(50px);
-webkit-transform: scaleY(50px);
transform: scaleY(50px); }
.scale-y-3d {
-moz-transform: scaleY(50px);
-webkit-transform: scaleY(50px);
transform: scaleY(50px); }
.scale-y-with-perspective {
-moz-transform: perspective(500) scaleY(50px);
-ms-transform: perspective(500) scaleY(50px);
-webkit-transform: perspective(500) scaleY(50px);
transform: perspective(500) scaleY(50px); }
.scale-y-3d-with-perspective {
-moz-transform: perspective(500) scaleY(50px);
-webkit-transform: perspective(500) scaleY(50px);
transform: perspective(500) scaleY(50px); }
.scale-z {
-moz-transform: scaleZ(50px);
-webkit-transform: scaleZ(50px);
transform: scaleZ(50px); }
.scale-z-with-perspective {
-moz-transform: perspective(500) scaleZ(50px);
-webkit-transform: perspective(500) scaleZ(50px);
transform: perspective(500) scaleZ(50px); }
.scale3d {
-moz-transform: scale3d(30px, 50px, 100px);
-webkit-transform: scale3d(30px, 50px, 100px);
transform: scale3d(30px, 50px, 100px); }
.scaled3-with-perspective {
-moz-transform: perspective(500) scale3d(30px, 50px, 100px);
-webkit-transform: perspective(500) scale3d(30px, 50px, 100px);
transform: perspective(500) scale3d(30px, 50px, 100px); }
.rotate {
-moz-transform: perspective(500) rotate(25deg);
-ms-transform: perspective(500) rotate(25deg);
-webkit-transform: perspective(500) rotate(25deg);
transform: perspective(500) rotate(25deg); }
.rotate-with-perspective {
-moz-transform: perspective(500) rotate(25deg);
-ms-transform: perspective(500) rotate(25deg);
-webkit-transform: perspective(500) rotate(25deg);
transform: perspective(500) rotate(25deg); }
.rotate-z {
-moz-transform: rotate(25deg);
-ms-transform: rotate(25deg);
-webkit-transform: rotate(25deg);
transform: rotate(25deg); }
.rotate-z-with-perspective {
-moz-transform: perspective(500) rotate(25deg);
-ms-transform: perspective(500) rotate(25deg);
-webkit-transform: perspective(500) rotate(25deg);
transform: perspective(500) rotate(25deg); }
.rotate-x {
-moz-transform: rotateX(25deg);
-webkit-transform: rotateX(25deg);
transform: rotateX(25deg); }
.rotate-x-with-perspective {
-moz-transform: perspective(500) rotateX(25deg);
-webkit-transform: perspective(500) rotateX(25deg);
transform: perspective(500) rotateX(25deg); }
.rotate-y {
-moz-transform: rotateY(25deg);
-webkit-transform: rotateY(25deg);
transform: rotateY(25deg); }
.rotate-y-with-perspective {
-moz-transform: perspective(500) rotateY(25deg);
-webkit-transform: perspective(500) rotateY(25deg);
transform: perspective(500) rotateY(25deg); }
.rotate-3d {
-moz-transform: rotate3d(5, 2, 1, 75deg);
-webkit-transform: rotate3d(5, 2, 1, 75deg);
transform: rotate3d(5, 2, 1, 75deg); }
.rotate-3d-with-perspective {
-moz-transform: perspective(500) rotate3d(5, 2, 1, 75deg);
-webkit-transform: perspective(500) rotate3d(5, 2, 1, 75deg);
transform: perspective(500) rotate3d(5, 2, 1, 75deg); }
.translate {
-moz-transform: translate(20px, 30%);
-ms-transform: translate(20px, 30%);
-webkit-transform: translate(20px, 30%);
transform: translate(20px, 30%); }
.translate-with-perspective {
-moz-transform: perspective(500) translate(20px, 30%);
-ms-transform: perspective(500) translate(20px, 30%);
-webkit-transform: perspective(500) translate(20px, 30%);
transform: perspective(500) translate(20px, 30%); }
.translate-3d {
-moz-transform: translate(20px, 30%);
-webkit-transform: translate(20px, 30%);
transform: translate(20px, 30%); }
.translate-3d-with-perspective {
-moz-transform: perspective(500) translate(20px, 30%);
-webkit-transform: perspective(500) translate(20px, 30%);
transform: perspective(500) translate(20px, 30%); }
.translate-x {
-moz-transform: translateX(30px);
-ms-transform: translateX(30px);
-webkit-transform: translateX(30px);
transform: translateX(30px); }
.translate-x-3d {
-moz-transform: translateX(30px);
-webkit-transform: translateX(30px);
transform: translateX(30px); }
.translate-x-with-perspective {
-moz-transform: perspective(500) translateX(30px);
-ms-transform: perspective(500) translateX(30px);
-webkit-transform: perspective(500) translateX(30px);
transform: perspective(500) translateX(30px); }
.translate-x-3d-with-perspective {
-moz-transform: perspective(500) translateX(30px);
-webkit-transform: perspective(500) translateX(30px);
transform: perspective(500) translateX(30px); }
.translate-y {
-moz-transform: translateY(30px);
-ms-transform: translateY(30px);
-webkit-transform: translateY(30px);
transform: translateY(30px); }
.translate-y-3d {
-moz-transform: translateY(30px);
-webkit-transform: translateY(30px);
transform: translateY(30px); }
.translate-y-with-perspective {
-moz-transform: perspective(500) translateY(30px);
-ms-transform: perspective(500) translateY(30px);
-webkit-transform: perspective(500) translateY(30px);
transform: perspective(500) translateY(30px); }
.translate-y-3d-with-perspective {
-moz-transform: perspective(500) translateY(30px);
-webkit-transform: perspective(500) translateY(30px);
transform: perspective(500) translateY(30px); }
.translate-z {
-moz-transform: translateZ(30px);
-webkit-transform: translateZ(30px);
transform: translateZ(30px); }
.translate-z-with-perspective {
-moz-transform: perspective(500) translateZ(30px);
-webkit-transform: perspective(500) translateZ(30px);
transform: perspective(500) translateZ(30px); }
.translate-3d {
-moz-transform: translate3d(30px, 50px, 75px);
-webkit-transform: translate3d(30px, 50px, 75px);
transform: translate3d(30px, 50px, 75px); }
.translate-3d-with-perspective {
-moz-transform: perspective(500) translate3d(30px, 50px, 75px);
-webkit-transform: perspective(500) translate3d(30px, 50px, 75px);
transform: perspective(500) translate3d(30px, 50px, 75px); }
.skew {
-moz-transform: skew(20deg, 50deg);
-ms-transform: skew(20deg, 50deg);
-webkit-transform: skew(20deg, 50deg);
transform: skew(20deg, 50deg); }
.skew-3d {
-moz-transform: skew(20deg, 50deg);
-webkit-transform: skew(20deg, 50deg);
transform: skew(20deg, 50deg); }
.skew-x {
-moz-transform: skewX(20deg);
-ms-transform: skewX(20deg);
-webkit-transform: skewX(20deg);
transform: skewX(20deg); }
.skew-x-3d {
-moz-transform: skewX(20deg);
-webkit-transform: skewX(20deg);
transform: skewX(20deg); }
.skew-y {
-moz-transform: skewY(20deg);
-ms-transform: skewY(20deg);
-webkit-transform: skewY(20deg);
transform: skewY(20deg); }
.skew-y-3d {
-moz-transform: skewY(20deg);
-webkit-transform: skewY(20deg);
transform: skewY(20deg); }
.create-transform-2d {
-moz-transform: perspective(500) scale(20px, 20px) rotateX(25deg) rotateY(25deg) rotate3d(false 50px) translateX(50px) translateZ(50deg) skew(50deg, 50%);
-ms-transform: perspective(500) scale(20px, 20px) rotateX(25deg) rotateY(25deg) rotate3d(false 50px) translateX(50px) translateZ(50deg) skew(50deg, 50%);
-webkit-transform: perspective(500) scale(20px, 20px) rotateX(25deg) rotateY(25deg) rotate3d(false 50px) translateX(50px) translateZ(50deg) skew(50deg, 50%);
transform: perspective(500) scale(20px, 20px) rotateX(25deg) rotateY(25deg) rotate3d(false 50px) translateX(50px) translateZ(50deg) skew(50deg, 50%);
-moz-transform-origin: 50%;
-ms-transform-origin: 50%;
-webkit-transform-origin: 50%;
transform-origin: 50%; }
.create-transform-3d {
-moz-transform: perspective(500) scale3d(20px, 20px, 20px) rotateX(25deg) rotateY(25deg) rotateZ(25deg) rotate3d(false 50px) translate3d(50px, 50px, 50deg) skew(50deg, 50%);
-ms-transform: perspective(500) scale3d(20px, 20px, 20px) rotateX(25deg) rotateY(25deg) rotateZ(25deg) rotate3d(false 50px) translate3d(50px, 50px, 50deg) skew(50deg, 50%);
-webkit-transform: perspective(500) scale3d(20px, 20px, 20px) rotateX(25deg) rotateY(25deg) rotateZ(25deg) rotate3d(false 50px) translate3d(50px, 50px, 50deg) skew(50deg, 50%);
transform: perspective(500) scale3d(20px, 20px, 20px) rotateX(25deg) rotateY(25deg) rotateZ(25deg) rotate3d(false 50px) translate3d(50px, 50px, 50deg) skew(50deg, 50%);
-moz-transform-origin: 50% 50%;
-ms-transform-origin: 50% 50%;
-webkit-transform-origin: 50% 50%;
transform-origin: 50% 50%; }
.simple-transform {
-moz-transform: scale(25px, 25px) rotateZ(25deg) translate(10px, 10px) skew(30deg, 30deg);
-ms-transform: scale(25px, 25px) rotateZ(25deg) translate(10px, 10px) skew(30deg, 30deg);
-webkit-transform: scale(25px, 25px) rotateZ(25deg) translate(10px, 10px) skew(30deg, 30deg);
transform: scale(25px, 25px) rotateZ(25deg) translate(10px, 10px) skew(30deg, 30deg);
-moz-transform-origin: 10% 10%;
-ms-transform-origin: 10% 10%;
-webkit-transform-origin: 10% 10%;
transform-origin: 10% 10%; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/transition.css
================================================
.single-transition-without-delay {
-moz-transition: all 0.6s ease-out;
-o-transition: all 0.6s ease-out;
-webkit-transition: all 0.6s ease-out;
transition: all 0.6s ease-out; }
.single-transition-with-delay {
-moz-transition: all 0.6s ease-out 0.2s;
-o-transition: all 0.6s ease-out 0.2s;
-webkit-transition: all 0.6s ease-out;
-webkit-transition-delay: 0.2s;
transition: all 0.6s ease-out 0.2s; }
.transition-duration-list {
-moz-transition-duration: 0.2s, 0.5s, 0.2s;
-o-transition-duration: 0.2s, 0.5s, 0.2s;
-webkit-transition-duration: 0.2s, 0.5s, 0.2s;
transition-duration: 0.2s, 0.5s, 0.2s; }
.multiple-transition-durations {
-moz-transition-duration: 0.2s, 0.5s, 0.2s;
-o-transition-duration: 0.2s, 0.5s, 0.2s;
-webkit-transition-duration: 0.2s, 0.5s, 0.2s;
transition-duration: 0.2s, 0.5s, 0.2s; }
.single-transform-transition-without-delay {
-moz-transition: -moz-transform 0.6s ease-out;
-o-transition: -o-transform 0.6s ease-out;
-webkit-transition: -webkit-transform 0.6s ease-out;
transition: transform 0.6s ease-out; }
.single-transform-transition-with-delay {
-moz-transition: -moz-transform 0.6s ease-out 0.2s;
-o-transition: -o-transform 0.6s ease-out 0.2s;
-webkit-transition: -webkit-transform 0.6s ease-out;
-webkit-transition-delay: 0.2s;
transition: transform 0.6s ease-out 0.2s; }
.transform-transition {
-moz-transition: -moz-transform 0.6s ease-out;
-o-transition: -o-transform 0.6s ease-out;
-webkit-transition: -webkit-transform 0.6s ease-out;
transition: transform 0.6s ease-out; }
.multiple-transitions {
-moz-transition: -moz-transform 0.6s ease-out, opacity 0.2s ease-in;
-o-transition: -o-transform 0.6s ease-out, opacity 0.2s ease-in;
-webkit-transition: -webkit-transform 0.6s ease-out, opacity 0.2s ease-in;
transition: transform 0.6s ease-out, opacity 0.2s ease-in; }
.transition-property {
-moz-transition-property: -moz-transform;
-o-transition-property: -o-transform;
-webkit-transition-property: -webkit-transform;
transition-property: transform; }
.transition-properties {
-moz-transition-property: -moz-transform, opacity, width, height, left, top;
-o-transition-property: -o-transform, opacity, width, height, left, top;
-webkit-transition-property: -webkit-transform, opacity, width, height, left, top;
transition-property: transform, opacity, width, height, left, top; }
.multiple-transition-properties {
-moz-transition-property: opacity, -moz-transform, left;
-o-transition-property: opacity, -o-transform, left;
-webkit-transition-property: opacity, -webkit-transform, left;
transition-property: opacity, transform, left; }
.default-transition {
-moz-transition: all 1s;
-o-transition: all 1s;
-webkit-transition: all 1s;
transition: all 1s; }
.transition-timing {
-moz-transition-timing-function: ease-in;
-o-transition-timing-function: ease-in;
-webkit-transition-timing-function: ease-in;
transition-timing-function: ease-in; }
.transition-timings {
-moz-transition-timing-function: ease-in, cubic-bezier(1, 0, 1, 0);
-o-transition-timing-function: ease-in, cubic-bezier(1, 0, 1, 0);
-webkit-transition-timing-function: ease-in, cubic-bezier(1, 0, 1, 0);
transition-timing-function: ease-in, cubic-bezier(1, 0, 1, 0); }
.transition-timings-list {
-moz-transition-timing-function: ease-in, cubic-bezier(1, 0, 1, 0);
-o-transition-timing-function: ease-in, cubic-bezier(1, 0, 1, 0);
-webkit-transition-timing-function: ease-in, cubic-bezier(1, 0, 1, 0);
transition-timing-function: ease-in, cubic-bezier(1, 0, 1, 0); }
.transition-delay {
-moz-transition-delay: 1s;
-o-transition-delay: 1s;
-webkit-transition-delay: 1s;
transition-delay: 1s; }
.transition-delays {
-moz-transition-delay: 1s, 2s, 3s;
-o-transition-delay: 1s, 2s, 3s;
-webkit-transition-delay: 1s, 2s, 3s;
transition-delay: 1s, 2s, 3s; }
.transition-delays-list {
-moz-transition-delay: 1s, 2s, 3s;
-o-transition-delay: 1s, 2s, 3s;
-webkit-transition-delay: 1s, 2s, 3s;
transition-delay: 1s, 2s, 3s; }
.regression-912 {
-moz-transition: background-color 0.5s ease-in 0s, width 0.5s ease-out 0s, height 0.5s ease-in 0s, top 0.5s ease-out 0s;
-o-transition: background-color 0.5s ease-in 0s, width 0.5s ease-out 0s, height 0.5s ease-in 0s, top 0.5s ease-out 0s;
-webkit-transition: background-color 0.5s ease-in, width 0.5s ease-out, height 0.5s ease-in, top 0.5s ease-out;
-webkit-transition-delay: 0s, 0s, 0s, 0s;
transition: background-color 0.5s ease-in 0s, width 0.5s ease-out 0s, height 0.5s ease-in 0s, top 0.5s ease-out 0s; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/typography/links/hover-link.css
================================================
a {
text-decoration: none; }
a:hover, a:focus {
text-decoration: underline; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/units.css
================================================
.foo {
width: 600px;
height: 200px; }
.foo .test {
/* 16px for margins should be 1em */
margin-top: 1em;
/* 16px for margins should be 2.66667% (relative to parent's width) */
margin-right: 2.66667%;
/* 1.35em for margins should be 3.6% (relative to parent's width,
* even for top and bottom margins) */
margin-bottom: 3.6%;
/* 16px for margins should be 2ex */
margin-left: 2ex; }
.bar {
font-size: 18px;
width: 360px; }
.bar .test {
/* 150% for line-height should be 27px */
line-height: 27px;
/* 1px should always be .0625rem for this page */
border-top: 0.0625rem;
/* 2em for this element should be 9.525mm (relative to own font-size, as inherited) */
margin-top: 9.525mm;
/* 2px for margins should be .55556% (relative to parent's width) */
margin-right: 0.55556%;
/* 1rem should always be 16px for this page, even when own font-size is 18px */
margin-bottom: 16px; }
.rem {
background-size: 400px, 100% 32px;
background-size: 25rem, 100% 2rem; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/user-interface.css
================================================
.user-select {
-moz-user-select: -moz-none;
-ms-user-select: none;
-webkit-user-select: none;
user-select: none; }
*:-moz-placeholder {
color: #bfbfbf;
font-style: italic; }
*::-moz-placeholder {
color: #bfbfbf;
font-style: italic; }
*:-ms-input-placeholder {
color: #bfbfbf;
font-style: italic; }
*::-webkit-input-placeholder {
color: #bfbfbf;
font-style: italic; }
input:-moz-placeholder, textarea:-moz-placeholder {
color: #bfbfbf;
font-style: italic; }
input::-moz-placeholder, textarea::-moz-placeholder {
color: #bfbfbf;
font-style: italic; }
input:-ms-input-placeholder, textarea:-ms-input-placeholder {
color: #bfbfbf;
font-style: italic; }
input::-webkit-input-placeholder, textarea::-webkit-input-placeholder {
color: #bfbfbf;
font-style: italic; }
.sets-up-browser-support-for-content:-moz-placeholder {
prefix: -moz;
-moz-prefix: true;
-ms-prefix: false;
-webkit-prefix: false; }
.sets-up-browser-support-for-content::-moz-placeholder {
prefix: -moz;
-moz-prefix: true;
-ms-prefix: false;
-webkit-prefix: false; }
.sets-up-browser-support-for-content:-ms-input-placeholder {
prefix: -ms;
-moz-prefix: false;
-ms-prefix: true;
-webkit-prefix: false; }
.sets-up-browser-support-for-content::-webkit-input-placeholder {
prefix: -webkit;
-moz-prefix: false;
-ms-prefix: false;
-webkit-prefix: true; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/utilities.css
================================================
.clearfix {
overflow: hidden;
*zoom: 1; }
.pie-clearfix {
*zoom: 1; }
.pie-clearfix:after {
content: "\0020";
display: block;
height: 0;
clear: both;
overflow: hidden;
visibility: hidden; }
.simple-pie-clearfix {
*zoom: 1; }
.simple-pie-clearfix:after {
content: "";
display: table;
clear: both; }
p.light {
background-color: #f3aead;
color: black; }
p.dark {
background-color: #a22321;
color: white; }
p.light-with-args {
background-color: #f3aead;
color: blue; }
p.dark-with-args {
background-color: #a22321;
color: yellow; }
th {
background-color: white; }
th.even, th:nth-child(2n) {
background-color: yellow; }
tr.odd td, tr:nth-child(2n+1) td {
background-color: white; }
tr.odd td.even, tr.odd td:nth-child(2n), tr:nth-child(2n+1) td.even, tr:nth-child(2n+1) td:nth-child(2n) {
background-color: yellow; }
tr.even td {
background-color: red; }
tr.even td.even, tr.even td:nth-child(2n) {
background-color: red; }
tfoot th, tfoot td {
background-color: white; }
tfoot th.even, tfoot th:nth-child(2n), tfoot td.even, tfoot td:nth-child(2n) {
background-color: yellow; }
p.ellipsis {
white-space: nowrap;
overflow: hidden;
-ms-text-overflow: ellipsis;
-o-text-overflow: ellipsis;
text-overflow: ellipsis; }
p.ellipsis.moz {
white-space: nowrap;
overflow: hidden;
-ms-text-overflow: ellipsis;
-o-text-overflow: ellipsis;
text-overflow: ellipsis;
-moz-binding: url('/tmp/xml/ellipsis.xml#ellipsis'); }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/vertical_rhythm.css
================================================
html {
font-size: 87.5%;
line-height: 1.14286em; }
.small {
font-size: 0.85714em;
line-height: 1.33333em; }
.padded {
margin-top: 1.14286em;
padding-top: 1.14286em;
padding-bottom: 1.14286em;
margin-bottom: 1.14286em; }
.small-padded {
font-size: 0.85714em;
line-height: 1.33333em;
margin-top: 1.33333em;
padding-top: 1.33333em;
padding-bottom: 1.33333em;
margin-bottom: 1.33333em; }
.borders {
border-top-width: 0.07143em;
border-top-style: solid;
padding-top: 1.07143em;
border-bottom-width: 0.07143em;
border-bottom-style: solid;
padding-bottom: 1.07143em; }
.large-borders {
font-size: 1.71429em;
line-height: 2em;
border-top-width: 0.25em;
border-top-style: solid;
padding-top: 0.41667em;
border-bottom-width: 0.25em;
border-bottom-style: solid;
padding-bottom: 0.41667em; }
.reset {
line-height: 1.14286em; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/vertical_rhythm_with_ems.css
================================================
/* New test using em output */
html {
font-size: 112.5%;
line-height: 1.4em; }
.container {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjEuMCIgeDI9IjAuNSIgeTI9IjAuMCI+PHN0b3Agb2Zmc2V0PSI1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjUiLz48c3RvcCBvZmZzZXQ9IjUlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
background-image: -webkit-gradient(linear, 50% 100%, 50% 0%, color-stop(5%, rgba(0, 0, 0, 0.5)), color-stop(5%, rgba(0, 0, 0, 0)));
background-image: -moz-linear-gradient(bottom, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%);
background-image: -webkit-linear-gradient(bottom, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%);
background-image: linear-gradient(to top, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%);
-moz-background-size: 100% 1.4em;
-o-background-size: 100% 1.4em;
-webkit-background-size: 100% 1.4em;
background-size: 100% 1.4em;
background-position: left top; }
p {
margin-top: 1.4em;
margin-bottom: 1.4em; }
th,
td {
padding-top: 0.35em;
padding-bottom: 0.35em; }
.caption {
font-size: 0.72222em;
line-height: 1.55077em; }
.spaced-out {
line-height: 2.1em; }
blockquote {
margin-top: 1.4em;
margin-bottom: 1.4em;
padding: 0 1.4em; }
.fig-quote > blockquote {
margin-bottom: 0.7em; }
.fig-quote .source {
font-size: 0.72222em;
line-height: 1.93846em;
margin-bottom: 0.96923em; }
.panel {
font-size: 0.88889em;
line-height: 1.575em;
border-width: 0.0625em;
border-style: solid;
border-color: #aaaaaa;
padding: 1.5125em; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/vertical_rhythm_with_px.css
================================================
/* New using px output */
html {
font-size: 18px;
line-height: 25px; }
.container {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjEuMCIgeDI9IjAuNSIgeTI9IjAuMCI+PHN0b3Agb2Zmc2V0PSI1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjUiLz48c3RvcCBvZmZzZXQ9IjUlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
background-image: -webkit-gradient(linear, 50% 100%, 50% 0%, color-stop(5%, rgba(0, 0, 0, 0.5)), color-stop(5%, rgba(0, 0, 0, 0)));
background-image: -moz-linear-gradient(bottom, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%);
background-image: -webkit-linear-gradient(bottom, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%);
background-image: linear-gradient(to top, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%);
-moz-background-size: 100% 25px;
-o-background-size: 100% 25px;
-webkit-background-size: 100% 25px;
background-size: 100% 25px;
background-position: left top; }
p {
margin-top: 25px;
margin-bottom: 25px; }
th,
td {
padding-top: 6px;
padding-bottom: 6px; }
/* Incremental leading made easy! */
.caption {
font-size: 15px;
line-height: 20px; }
.spaced-out {
line-height: 37px; }
blockquote {
margin-top: 25px;
margin-bottom: 25px;
padding: 0 25px; }
.fig-quote > blockquote {
margin-bottom: 12px; }
.fig-quote .source {
font-size: 15px;
line-height: 25px;
margin-bottom: 12px; }
.panel {
border-width: 1px;
border-style: solid;
border-color: #aaaaaa;
padding: 24px; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/css/vertical_rhythm_with_rems.css
================================================
/* New using rem output with pixel fallbacks */
html {
font-size: 112.5%;
line-height: 1.4em; }
.container {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjEuMCIgeDI9IjAuNSIgeTI9IjAuMCI+PHN0b3Agb2Zmc2V0PSI1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjUiLz48c3RvcCBvZmZzZXQ9IjUlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
background-size: 100%;
background-image: -webkit-gradient(linear, 50% 100%, 50% 0%, color-stop(5%, rgba(0, 0, 0, 0.5)), color-stop(5%, rgba(0, 0, 0, 0)));
background-image: -moz-linear-gradient(bottom, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%);
background-image: -webkit-linear-gradient(bottom, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%);
background-image: linear-gradient(to top, rgba(0, 0, 0, 0.5) 5%, rgba(0, 0, 0, 0) 5%);
-moz-background-size: 100% 1.4rem;
-o-background-size: 100% 1.4rem;
-webkit-background-size: 100% 1.4rem;
background-size: 100% 1.4rem;
background-position: left top; }
p {
margin-top: 25px;
margin-top: 1.4rem;
margin-bottom: 25px;
margin-bottom: 1.4rem; }
th,
td {
padding-top: 6px;
padding-top: 0.35rem;
padding-bottom: 6px;
padding-bottom: 0.35rem; }
/* Incremental leading made easy! */
.caption {
font-size: 15px;
font-size: 0.85rem;
line-height: 20px;
line-height: 1.12rem; }
.spaced-out {
line-height: 38px;
line-height: 2.1rem; }
blockquote {
margin-top: 25px;
margin-top: 1.4rem;
margin-bottom: 25px;
margin-bottom: 1.4rem;
padding: 0 1.4rem; }
.fig-quote > blockquote {
margin-bottom: 13px;
margin-bottom: 0.7rem; }
.fig-quote .source {
font-size: 15px;
font-size: 0.85rem;
line-height: 25px;
line-height: 1.4rem;
margin-bottom: 13px;
margin-bottom: 0.7rem; }
.panel {
border-width: 1px;
border-width: 0.05556rem;
border-style: solid;
border-color: #aaaaaa;
padding: 24px;
padding: 1.34444rem; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/animation-with-legacy-ie.scss
================================================
@import "compass/css3/animation";
@import "compass/css3/opacity";
$browser-minimum-versions: (ie: "6");
@include keyframes(test) {
0%, 100% {
@include opacity(1);
}
50% {
@include opacity(0);
}
}
.animation {
@include animation(test);
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/animation.scss
================================================
@import "compass/css3/animation";
@include keyframes(test) {
0%, 100% {
background-color: red; }
50% {
background-color: blue;
}
}
.animation {
@include animation(test);
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/appearance.scss
================================================
@import "compass/css3/appearance";
.searchfield {
@include appearance(searchfield);
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/background-clip.scss
================================================
@import "compass/css3/background-clip";
.background-clip { @include background-clip('border-box'); }
.background-clip-multiple { @include background-clip('border-box', padding-box, content-box); }
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/background-origin.scss
================================================
@import "compass/css3/background-origin";
.background-origin { @include background-origin('border-box'); }
.background-origin-multiple { @include background-origin('border-box', padding-box, content-box); }
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/background-size.scss
================================================
@import "compass/css3/background-size";
.background-size-default { @include background-size; }
.background-size-single { @include background-size(50% 25%); }
.background-size-multiple { @include background-size(4em 3em, $default-background-size, 50%); }
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/border_radius.scss
================================================
@import "compass/css3/border-radius";
.simple { @include border-radius(4px, 4px); }
.compound { @include border-radius(2px 5px, 3px 6px); }
.crazy { @include border-radius(1px 3px 5px 7px, 2px 4px 6px 8px)}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/box-sizing.scss
================================================
@import "compass/css3/box-sizing";
.div {
@include box-sizing();
}
.div {
@include box-sizing(content-box);
}
.div {
@include box-sizing(border-box);
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/box.sass
================================================
@import compass/css3/box
.hbox
+display-box
+box-orient
+box-align
& > *
+box-flex
.vbox
+display-box
+box-orient(vertical)
+box-align
& > *
+box-flex
.spacer
+box-flex(1)
.reverse
+box-direction(reverse)
.box-flex-0
+box-flex(0)
.box-flex-1
+box-flex(1)
.box-flex-2
+box-flex(2)
.box-flex-group-0
+box-flex-group(0)
.box-flex-group-1
+box-flex-group(1)
.box-flex-group-2
+box-flex-group(2)
.start
+box-pack(start)
.end
+box-pack(end)
.center
+box-pack(center)
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/box_shadow.scss
================================================
@import "compass/css3/box-shadow";
.no-box-shadow { @include box-shadow(none); }
.box-shadow { @include box-shadow(default, 2px 2px 5px #222222);}
.single-box-shadow { @include single-box-shadow;}
.multiple-box-shadows { @include box-shadow(default, 2px 2px 5px #222222);}
.legacy-single-box-shadow { @include single-box-shadow(blue);}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/brightness.scss
================================================
@import "compass/utilities/color/brightness";
.black-is-0-percent {
brightness: brightness(black); }
.white-is-100-percent {
brightness: brightness(white); }
.green-is-58-point-7-percent {
brightness: brightness(#00ff00); }
.blue-is-11-point-4-percent {
brightness: brightness(#0000ff); }
.red-is-29-point-9-percent {
brightness: brightness(#ff0000); }
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/browser-support.scss
================================================
@import "compass/support";
@import "compass/css3/flexbox";
@function unprefixed-at-version($browser, $capability) {
$options: if($capability == flexbox, $flexbox-capability-options, $default-capability-options);
@each $version in browser-versions($browser) {
@if not browser-requires-prefix($browser, $version, $capability, $options) {
@return $version;
}
}
@return null;
}
@each $browser in browsers() {
$prefix: browser-prefix($browser);
.#{$browser} {
$versions: browser-versions($browser);
versions: $versions;
@each $capability in browser-capabilities() {
$options: if($capability == flexbox, $flexbox-capability-options, $default-capability-options);
@if browser-requires-prefix($browser, nth($versions, 1), $capability, $options) {
@if prefix-usage($prefix, $capability, $options) > 0.1 {
#{$capability}: $prefix;
} @else {
#{$capability}: prefix-no-longer-needed;
}
#{$capability}-unprefixed-at: unprefixed-at-version($browser, $capability);
}
}
}
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/color.scss
================================================
$contrasted-dark-default: black;
$contrasted-light-default: white;
@import "compass/utilities/color";
.handles-null {
content: "there should be no property below this one";
color: contrast-color(null);
}
.contrasts-light {
@include contrasted(#eeeeee);
}
.contrasts-dark {
@include contrasted(#222222);
}
.contrasts-light-with-contrast-color-override {
@include contrasted(#eeeeee, $dark: red);
}
.contrasts-dark-with-contrast-color-override {
@include contrasted(#222222, $light: yellow);
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/columns.scss
================================================
@import "compass/css3/columns";
.columns { @include columns(20em 5); }
.column-count { @include column-count(5); }
.column-gap { @include column-gap(10px); }
.column-width { @include column-width(90px); }
.column-span { @include column-span(all); }
.column-rule-width { @include column-rule-width(1px); }
.column-rule-style { @include column-rule-style(dotted); }
.column-rule-color { @include column-rule-color(blue); }
.column-rule { @include column-rule(1px, solid, blue); }
.column-rule-spaced { @include column-rule(1px solid blue); }
.column-break-before{ @include column-break(before, always);}
.column-break-after { @include column-break(after, always); }
.column-break-inside{ @include column-break(inside); }
.column-count { @include column-count(5); }
.column-gap { @include column-gap(10px); }
.column-width { @include column-width(90px); }
.column-rule-width { @include column-rule-width(1px); }
.column-rule-style { @include column-rule-style(dotted); }
.column-rule-color { @include column-rule-color(blue); }
.column-rule { @include column-rule(1px, solid, blue); }
.column-rule-spaced { @include column-rule(1px solid blue); }
.column-break-before { @include break-before(always); }
.column-break-after { @include break-after(always); }
.column-break-inside { @include break-inside(); }
.column-break-before-shortcut { @include column-break(before, always);}
.column-break-after-shortcut { @include column-break(after, always); }
.column-break-inside-shortcut { @include column-break(inside); }
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/filters.scss
================================================
$debug-browser-support: true;
@import "compass/css3/filter";
.blur {
@include filter(blur(5px));
}
.brightness {
@include filter(brightness(0.2));
}
// We can enable this test case when sass commit 38f3c4be8bc15c130c5b1cc5880c9131e1bcb08f is released.
// .saturate {
// @include filter(saturate(50%));
// }
.hue-rotate {
@include filter(hue-rotate(20deg));
}
.contrast {
@include filter(contrast(150%));
}
.grayscale {
@include filter(grayscale(150%));
}
.sepia {
@include filter(sepia(150%));
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/flexbox.scss
================================================
@import "compass/css3/flexbox";
.display {
@include display-flex;
}
.flex-direction {
@include flex-direction(row-reverse);
}
.flex-wrap {
@include flex-wrap(wrap-reverse);
}
.flex-flow {
@include flex-flow(row-reverse wrap-reverse);
}
.order {
@include order(1);
}
.flex {
@include flex(1 0 auto);
}
.flex-grow {
@include flex-grow(1);
}
.flex-shrink {
@include flex-shrink(1);
}
.flex-basis {
@include flex-basis(auto);
}
.justify-content {
@include justify-content(flex-start);
}
.align-items {
@include align-items(flex-start);
}
.align-self {
@include align-self(flex-start);
}
.align-content {
@include align-content(flex-start);
}
.flexbox {
@include flexbox((
display: flex,
flex-direction: row-reverse,
flex-wrap: wrap-reverse,
flex-flow: row-reverse wrap-reverse,
order: 1,
flex: 1 0 auto,
flex-grow: 1,
flex-shrink: 0,
flex-basis: auto,
justify-content: flex-start,
align-items: flex-start,
align-self: flex-start,
align-content: flex-start
));
}
.flexbox-2 {
@include flexbox((
display: flexbox,
flex-flow: row-reverse,
flex-order: 1,
), $version: 2);
}
.flexbox-1 {
@include flexbox((
display: box,
box-orient: vertical,
box-ordinal-group: 1,
box-flex: 1,
), $version: 1);
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/fonts.sass
================================================
@import compass/css3/font-face
+font-face("font1", font-files("font1.woff", woff), "font1.eot")
@font-face
font-family: 'Issue1491'
src: font-url('font1.eot')
src: font-url('font1.eot?#iefix') format('embedded-opentype'), font-url('font1.woff') format('woff')
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/force-wrap.scss
================================================
@import "compass/typography/text";
pre { @include force-wrap; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/gradients.sass
================================================
@import compass/css3/images
$svg-gradient-shim-threshold: 0
.bg-shortcut-simple-image
+background(white url('foo.png'))
.bg-shortcut-linear-gradient
+background(white linear-gradient(top left, #ddd, #aaa))
.bg-shortcut-radial-gradient
+background(white radial-gradient(center center, #ddd, #aaa 100px))
.bg-linear-gradient-angle-svg
+background-image(linear-gradient(-45deg, blue, black))
.bg-linear-gradient-angle2-svg
+background-image(linear-gradient(top left, blue, black))
.bg-all-gradient-types-with-simplification
+background-with-css2-fallback(image-url("4x6.png"), linear-gradient(top left, #ddd, #aaa), radial-gradient(center center, #ddd, #aaa 100px), #ffcc00)
.bg-simple-image
+background-image(url('foo.png'))
.bg-linear-gradient
+background-image(linear-gradient(top left, #ddd, #aaa))
.bg-linear-gradient-pixel-stop-from-top
+background-image(linear-gradient(top, #ddd 10px, #aaa 40px))
.bg-linear-gradient-pixel-stop-from-left
+background-image(linear-gradient(left, #ddd 10px, #aaa 40px))
.transparent-in-linear-gradient
+background-image(white linear-gradient(top left, transparent, #aaa))
.currentColor-in-linear-gradient
+background-image(white linear-gradient(top left, transparent, currentColor))
.rgba-in-linear-gradient
+background-image(white linear-gradient(top left, rgba(255,255,255,0.8), rgba(0,0,0,0.1)))
.bg-radial-gradient
+background-image(radial-gradient(center center, #ddd, transparent 100px))
.currentColor-in-radial-gradient
+background-image(radial-gradient(center center, currentColor, transparent 100px))
.bg-linear-gradient-with-angle
+background-image(linear-gradient(-45deg, #ddd, #aaa))
.bg-radial-gradient-with-angle-and-shape
+background-image(radial-gradient(ellipse cover, #ddd, #aaa 100px))
.bg-all-gradient-types
+background-image(image-url("4x6.png"), linear-gradient(top left, #ddd, #aaa), radial-gradient(center center, #ddd, #aaa 100px))
.border-image-gradient
+border-image(radial-gradient(#0f0,#f00 100px) 100 stretch)
.direct-list-image-plain
+list-style-image(image-url("4x6.png"))
.shorthand-list-image-plain
+list-style(outside image-url("4x6.png"))
.direct-list-image-with-gradient
+list-style-image(radial-gradient(lime, red 10px))
.shorthand-list-image-with-gradient
// Note: I haven't seen a browser render this correctly, but they should eventually.
+list-style(outside radial-gradient(lime, red 10px))
.content-plain
+content("asdf")
.content-with-gradient
+content(radial-gradient(lime, red 10px))
$svg-gradient-shim-threshold: 10
.bg-linear-gradient-no-position
+background-image(linear-gradient(#ddd, #aaa))
.bg-radial-gradient-no-position
+background-image(radial-gradient(#ddd, #aaa 100px))
.image-fallback
+background-image(image(radial-gradient(#ddd, #aaa 100px), image-url("4x6.png"), #cc0000))
.cross-fade
+background-image(cross-fade(radial-gradient(#ddd, #aaa 100px), image-url("4x6.png")))
.unknown-function-wrapper
+background(foo(radial-gradient(#ddd, #aaa 100px)))
.ie-horizontal-filter
+filter-gradient(white, black, horizontal)
.ie-vertical-filter
+filter-gradient(white, black, vertical)
.ie-alpha-filter
+filter-gradient(rgba(white, 1), rgba(white, 0))
.linear-gradient-new
+background(linear-gradient(to bottom, #ff0000 0%, #88aa44 100%))
$use-legacy-gradient-syntax: true
.linear-gradient-old
+background(linear-gradient(top, #ff0000 0%, #88aa44 100%))
// This setting is only important when we can't tell which syntax is being used.
// * That is only ever true when the angle is specified in deg
// * original webkit syntax does not support deg (see output)
// * if $support-for-original-webkit-gradients and type-of($angle) == "number" : @WARN
$use-legacy-gradient-syntax: false
.linear-gradient-unknown-new
+background(linear-gradient(120deg, #ff0000 0%, #88aa44 100%))
$use-legacy-gradient-syntax: true
.linear-gradient-unknown-old
+background(linear-gradient(120deg, #ff0000 0%, #88aa44 100%))
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/grid_background.scss
================================================
@import "compass/layout/grid-background";
.baseline {
@include baseline-grid-background;
}
.columns {
@include column-grid-background;
}
.combined {
@include grid-background;
}
$grid-background-total-columns: 15;
$grid-background-offset: 11%;
$grid-background-column-width: 5%;
$grid-background-gutter-width: 1%;
.percent-baseline {
@include baseline-grid-background;
}
.percent-columns {
@include column-grid-background;
}
.percent-combined {
@include grid-background;
}
.forced-fluid {
@include column-grid-background(12, 2em, 1em, 1em, $grid-background-column-color, $grid-background-gutter-color, true);
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/hyphenation.scss
================================================
@import "compass/css3/hyphenation";
.word-break {
@include word-break(keep-all);
}
.hyphens {
@include hyphens(manual);
}
.hyphenate {
@include hyphenation;
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/image_size.sass
================================================
.png
width: image_width(unquote("100x150.png"))
height: image_height(unquote("100x150.png"))
.jpg
width: image_width(unquote("100x150.jpg"))
height: image_height(unquote("100x150.jpg"))
.jpeg
width: image_width(unquote("100x150.jpeg"))
height: image_height(unquote("100x150.jpeg"))
.gif
width: image_width(unquote("100x150.gif"))
height: image_height(unquote("100x150.gif"))
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/images.scss
================================================
.relative {
background-image: image-url("4x6.png");
}
.root-relative {
background-image: image-url("/images/4x6.png");
}
.absolute {
background-image: image-url("http://example.com/images/4x6.png");
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/layout.sass
================================================
@import compass/layout
+sticky-footer(72px, unquote("#layout"), unquote("#layout_footer"), unquote("#footer"))
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/legacy_clearfix.scss
================================================
$default-has-layout-approach: block;
@import "compass/utilities";
.clearfix {
@include clearfix;
}
.pie-clearfix {
@include legacy-pie-clearfix;
}
.simplified-pie-clearfix {
@include pie-clearfix;
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/lists.scss
================================================
@import "compass/typography/lists";
ul.horizontal { @include horizontal-list; }
ul.wide-horizontal { @include horizontal-list(10px); }
ul.right-horizontal { @include horizontal-list(4px, right); }
ul.no-padding { @include horizontal-list(false); }
ul.inline-block { @include inline-block-list; }
ul.wide-inline-block { @include inline-block-list(10px); }
ul.inline { @include inline-list; }
ul.comma { @include delimited-list; }
ul.no-bullets { @include no-bullets; }
ul.pretty { @include pretty-bullets("4x6.png"); }
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/opacity.scss
================================================
@import "compass/css3/opacity";
div {
@include opacity(1);
}
div {
@include opacity(.2);
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/print.sass
================================================
@import compass/utilities/print
+print-utilities
+print-utilities(screen)
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/regions.scss
================================================
@import "compass/css3/regions";
.source { @include flow-into(target); }
.new-container { @include flow-from(target); }
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/replacement.scss
================================================
@import "compass/typography/text/replacement";
.basic {
@include replace-text("4x6.png");
}
.with-dimensions {
@include replace-text-with-dimensions("4x6.png");
}
.with-dimensions-inline {
@include replace-text-with-dimensions("4x6.png", $inline: true);
}
.with-position {
@include replace-text("4x6.png", 10px, top);
}
.with-arbitrary-url {
@include replace-text(url(http://google.com/logo.gif), 10px, top);
}
.with-inline-url {
@include replace-text(inline-image("4x6.png"), 10px, top);
}
.with-image-url {
@include replace-text(image-url("4x6.png"), 10px, top);
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/reset.sass
================================================
@import compass/reset
// Turn off the display for both of these classes
.unregistered-only, .registered-only
display: none
// Now turn only one of them back on depending on some other context.
body.registered
+reset-display(unquote(".registered-only"))
body.unregistered
+reset-display(unquote(".unregistered-only"))
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/selection.scss
================================================
$contrasted-dark-default: black;
$contrasted-light-default: white;
@import "compass/css3/selection";
* {
@include selection {
background-color: #fe57a1;
color: #fff;
}
}
.hot-pink {
@include selection {
background-color: #fe57a1;
color: #fff;
}
}
.hot-pink-with-arguments {
@include selection(#fe57a1, white);
}
.hot-pink-with-arguments-and-extra-stuff {
@include selection(#fe57a1, white) {
text-decoration: line-through;
}
}
.hot-pink-with-default-foreground {
@include selection(#fe57a1);
}
.browser-support-is-considered {
@include selection(#fe57a1) {
prefix: $current-prefix;
-moz-prefix: $current-prefix == -moz;
-ms-prefix: $current-prefix == -ms;
-webkit-prefix: $current-prefix == -webkit;
}
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/sprites_with_explicit_separator.scss
================================================
$flag_states-sprite-dimensions: true;
$flag_states-class-separator: "_";
@import "flag_states/*.png";
@include all-flag_states-sprites;
.sprite-file {
location: image-url(sprite_file($flag-states-sprites, foo));
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/stretching.sass
================================================
@import "compass/layout/stretching"
.stretched-completely
+stretch
.stretched-horizontally
+stretch-x
.stretched-right
+stretch-x(0, 50%)
.left-pane
+stretch(0, 50%, 0, 0)
.stretched-left
+stretch-x(50%, 0)
.right-pane
+stretch(0, 0, 0, 50%)
.stretched-down
+stretch-y(0, 50%)
.top-pane
+stretch(0, 0, 50%, 0)
.stretched-up
+stretch-y(50%, 0)
.bottom-pane
+stretch(50%, 0, 0, 0)
.viewport
+stretch(10px, 20px, 30px, 40px)
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/support.scss
================================================
@import "compass/css3/animation";
@import "compass/css3/opacity";
@import "true";
$some-default-value: some default value;
@function has-default-arglist($arglist...) {
@return set-arglist-default($arglist, $some-default-value);
}
@mixin with-declared-support($browsers) {
$old-browsers: $supported-browsers;
$supported-browsers: $browsers !global;
@content;
$supported-browsers: $old-browsers !global;
}
@mixin with-declared-minimums($supported-browsers) {
$old-mins: $browser-minimum-versions;
$browser-minimum-versions: $supported-browsers !global;
@content;
$browser-minimum-versions: $old-mins !global;
}
@include test-module('Compass Support') {
@include test('[function] set-arglist-default() with no arguments') {
@include assert-true(
has-default-arglist() == $some-default-value,
'No arguments should get a default value.');
}
@include test('[function] set-arglist-default() with a "default" argument') {
@include assert-true(
nth(has-default-arglist(default), 1) == $some-default-value,
'an argument of "default" should get a default value.');
}
@include test('[function] set-arglist-default() with a "default" argument and another argument') {
@include assert-true(
has-default-arglist(default, some other value) == ($some-default-value, some other value),
'an argument of "default" should get a default value.');
}
@include test('[function] set-arglist-default() with a "default" argument not first and another argument') {
@include assert-true(
has-default-arglist(some other value, default) == (some other value, $some-default-value),
'an argument of "default" should get a default value.');
}
@include test('[function] support-legacy-browser() from threshold') {
@include assert-true(support-legacy-browser('ie', '6', $threshold: 0.00000001),
"should be supported because of user support threshold.");
@include assert-false(support-legacy-browser('ie', '6', $threshold: 10.000),
"should not be supported because of support threshold.");
}
@include test('[function] support-legacy-browser() from minimums') {
@include with-declared-minimums(('ie': '7')) {
@include assert-true(support-legacy-browser('ie', '7', $threshold: 10.00),
"should be supported because of minimum version.");
@include assert-false(support-legacy-browser('ie', '6', $threshold: 10.000),
"should not be supported because of minimum version.");
}
}
@include test('[function] browser-out-of-scope() with no scope') {
@include assert-true(not browser-out-of-scope('ie'), "should be in scope.");
@include assert-true(not browser-out-of-scope('chrome'), "should be in scope.");
}
@include test('prefix context tracking') {
$outer-prefix-invoked: false;
$inner-prefix-invoked: false;
$mismatched-prefix-invoked: false;
@include with-prefix(-webkit) {
$outer-prefix-invoked: true;
@include assert-equal(-webkit, $current-prefix, "should be equal.");
@include assert-equal(-webkit, $prefix-context, "should be equal.");
@include with-prefix(null) {
$inner-prefix-invoked: true;
@include assert-equal(null, $current-prefix, "should be equal.");
@include assert-equal(-webkit, $prefix-context, "should be equal.");
}
@include with-prefix(-ms) {
$mismatched-prefix-invoked: true;
}
}
@include assert-true($inner-prefix-invoked, "should have been invoked");
@include assert-true($outer-prefix-invoked, "should have been invoked");
@include assert-false($mismatched-prefix-invoked, "should not have been invoked");
@include assert-equal(null, $prefix-context, "should be null");
@include assert-equal(null, $current-prefix, "should be null");
}
@include test('[function] browser-out-of-scope() with a scope') {
@include with-prefix(browser-prefix('chrome')) {
@include assert-true(not browser-out-of-scope('chrome'), "should be in scope.");
@include assert-false(not browser-out-of-scope('ie'), "should not be in scope.");
}
}
@include test('[function] browser-out-of-scope() with version') {
@include with-browser-ranges((ie: '8' '8')) {
@include assert-false(not browser-out-of-scope('ie', '10'), "should not be in scope.");
@include assert-true(not browser-out-of-scope('ie', '8'), "should be in scope.");
@include assert-false(not browser-out-of-scope('ie', '7'), "should not be in scope.");
}
}
@include test('[mixin] with-prefix()') {
@include assert-true($current-prefix == null, "should be null.");
@include with-prefix(-webkit) {
@include assert-true($current-prefix == -webkit, "should be set.");
$called: false;
@include with-prefix(-webkit) {
$called: true;
}
@include assert-true($called, "should be called.");
$called: false;
@include with-prefix(-ms) {
$called: true;
}
@include assert-false($called, "should not be called.");
}
}
@include test('[mixin] with-each-prefix()') {
$prefixes: ();
@include with-each-prefix(css-regions, 0.0001) {
$prefixes: append($prefixes, $current-prefix);
}
@include assert-equal((-ms -webkit null), $prefixes, "Not equal");
}
@include test('[mixin] with-each-prefix() respects $supported-browsers') {
@include with-declared-support("ie") {
$prefixes: ();
@include with-each-prefix(css-regions, 0.0001) {
$prefixes: append($prefixes, $current-prefix);
}
@include assert-equal((-ms null), $prefixes, "Not equal");
}
}
@include test('[mixin] with-each-prefix() respects $current-prefix') {
$contexts: ();
$prefixes: ();
@include with-prefix(-webkit) {
$prefixes: append($prefixes, $current-prefix);
$contexts: append($contexts, $prefix-context);
@include with-each-prefix(css-regions, 0.0001) {
$prefixes: append($prefixes, $current-prefix);
$contexts: append($contexts, $prefix-context);
}
}
@include assert-true(index($prefixes, null), "Must have a null");
@include assert-equal((-webkit -webkit null), $prefixes, "Not equal");
@include assert-equal((-webkit -webkit -webkit), $contexts, "Not equal");
}
@include test('[fuction] has-browser-subset()') {
@include assert-true(has-browser-subset((firefox: "16" "25"), (firefox: "2" "25")), "Should detect version overlap");
@include assert-true(not has-browser-subset((firefox: "16" "25"), (firefox: "2" "15")), "Should not detect version overlap");
@include assert-true(not has-browser-subset((firefox: "2" "15"), (firefox: "16" "25")), "Should not detect version overlap");
@include assert-true(has-browser-subset((firefox: "16" "24"), (firefox: "2" "25")), "Should detect version overlap");
@include assert-true(has-browser-subset((firefox: "2" "25"), (firefox: "16" "24")), "Should detect version overlap");
}
}
@include with-browser-support-debugging {
@include keyframes(foo) {
0% { @include opacity(0); }
100% { @include opacity(1); }
}
.foo {
@include animation(foo 1s);
}
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/text_shadow.scss
================================================
$default-text-shadow-color: #aaaaaa;
@import "compass/css3/text-shadow";
.default-single-text-shadow { @include single-text-shadow;}
.none { @include single-text-shadow(none);}
.color-only { @include single-text-shadow(#cccccc);}
.color-first-with-params { @include single-text-shadow(#cccccc, 2px, 2px, 5px, 2px);}
.color-last-with-params { @include single-text-shadow(2px, 2px, 5px, 2px, #cccccc);}
.default-text-shadow { @include text-shadow;}
.multiple-text-shadows-with-default { @include text-shadow(default, 2px 2px 5px #222222);}
.multiple-text-shadows { @include text-shadow(4px 4px 10px #444444, 2px 2px 5px #222222);}
.multiple-text-shadows-with-spread { @include text-shadow(4px 4px 10px 1px #444444, 2px 2px 5px 3px #222222);}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/transform.scss
================================================
@import "compass/css3/transform";
.apply-origin-2d { @include apply-origin(2px 5%, false); }
.apply-origin-3d { @include apply-origin(2px 5% 2in, true); }
.transform-origin-2d { @include transform-origin(100px, 100px); }
.transform-origin-3d { @include transform-origin(100px, 100px, 100px); }
.transform-2d { @include transform2d(rotateY(20deg)); }
.transform-3d { @include transform3d(rotateZ(20deg)); }
.perspective { @include perspective(500); }
.perspective-origin { @include perspective-origin(25% 25%)}
.transform-style { @include transform-style; }
.backface-visibility { @include backface-visibility;}
.scale { @include scale(30px, 50px);}
.scale-3d { @include scale(30px, 50px, false, true);}
.scale-with-perspective { @include scale(30px, 50px, 500);}
.scale-3d-with-perspective { @include scale(30px, 50px, 500, true);}
.scale-x { @include scaleX(30px);}
.scale-x-3d { @include scaleX(30px, false, true);}
.scale-x-with-perspective { @include scaleX(30px, 500);}
.scale-x-3d-with-perspective { @include scaleX(30px, 500, true);}
.scale-y { @include scaleY(50px);}
.scale-y-3d { @include scaleY(50px, false, true);}
.scale-y-with-perspective { @include scaleY(50px, 500);}
.scale-y-3d-with-perspective { @include scaleY(50px, 500, true);}
.scale-z { @include scaleZ(50px);}
.scale-z-with-perspective { @include scaleZ(50px, 500);}
.scale3d { @include scale3d(30px, 50px, 100px);}
.scaled3-with-perspective { @include scale3d(30px, 50px, 100px, 500);}
.rotate { @include rotate(25deg, 500);}
.rotate-with-perspective { @include rotate(25deg, 500);}
.rotate-z { @include rotateZ(25deg);}
.rotate-z-with-perspective { @include rotateZ(25deg, 500);}
.rotate-x { @include rotateX(25deg);}
.rotate-x-with-perspective { @include rotateX(25deg, 500);}
.rotate-y { @include rotateY(25deg);}
.rotate-y-with-perspective { @include rotateY(25deg, 500);}
.rotate-3d { @include rotate3d(5, 2, 1, 75deg);}
.rotate-3d-with-perspective { @include rotate3d(5, 2, 1, 75deg, 500);}
.translate { @include translate(20px, 30%);}
.translate-with-perspective { @include translate(20px, 30%, 500);}
.translate-3d { @include translate(20px, 30%, false, true);}
.translate-3d-with-perspective { @include translate(20px, 30%, 500, true);}
.translate-x { @include translateX(30px);}
.translate-x-3d { @include translateX(30px, false, true);}
.translate-x-with-perspective { @include translateX(30px, 500);}
.translate-x-3d-with-perspective { @include translateX(30px, 500, true);}
.translate-y { @include translateY(30px);}
.translate-y-3d { @include translateY(30px, false, true);}
.translate-y-with-perspective { @include translateY(30px, 500);}
.translate-y-3d-with-perspective { @include translateY(30px, 500, true);}
.translate-z { @include translateZ(30px);}
.translate-z-with-perspective { @include translateZ(30px, 500);}
.translate-3d { @include translate3d(30px, 50px, 75px);}
.translate-3d-with-perspective { @include translate3d(30px, 50px, 75px, 500);}
.skew { @include skew(20deg, 50deg);}
.skew-3d { @include skew(20deg, 50deg, true);}
.skew-x { @include skewX(20deg);}
.skew-x-3d { @include skewX(20deg, true);}
.skew-y { @include skewY(20deg);}
.skew-y-3d { @include skewY(20deg, true);}
.create-transform-2d { @include create-transform(
500,
20px, 20px, false,
25deg, 25deg, false, false
50px, 50px, false,
50deg, 50deg,
50%, 50%, false
);
}
.create-transform-3d { @include create-transform(
500,
20px, 20px, 20px,
25deg, 25deg, 25deg, false
50px, 50px, 50px,
50deg, 50deg,
50%, 50%, 50%
);
}
.simple-transform { @include simple-transform(
25px,
25deg,
10px, 10px,
30deg, 30deg,
10%, 10%
);
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/transition.scss
================================================
@import "compass/css3/transition";
.single-transition-without-delay { @include single-transition(all, 0.6s, ease-out); }
.single-transition-with-delay { @include single-transition(all, 0.6s, ease-out, 0.2s); }
.transition-duration-list { @include transition-duration((0.2s, 0.5s, 0.2s)); }
.multiple-transition-durations { @include transition-duration(0.2s, 0.5s, 0.2s); }
.single-transform-transition-without-delay { @include single-transition(transform, 0.6s, ease-out); }
.single-transform-transition-with-delay { @include single-transition(transform, 0.6s, ease-out, 0.2s); }
.transform-transition { @include transition(transform 0.6s ease-out) }
.multiple-transitions { @include transition(transform 0.6s ease-out, opacity 0.2s ease-in) }
.transition-property { @include transition-property(transform); }
.transition-properties { @include transition-property(transform, opacity, width, height, left, top); }
.multiple-transition-properties { @include transition-property((opacity, transform, left)); }
.default-transition { @include transition(); }
.transition-timing { @include transition-timing-function(ease-in); }
.transition-timings { @include transition-timing-function(ease-in, cubic-bezier(1,0,1,0)); }
.transition-timings-list { @include transition-timing-function((ease-in, cubic-bezier(1,0,1,0))); }
.transition-delay { @include transition-delay(1s); }
.transition-delays { @include transition-delay(1s, 2s, 3s); }
.transition-delays-list { @include transition-delay((1s, 2s, 3s)); }
.regression-912 { @include transition((background-color 0.5s ease-in 0s, width 0.5s ease-out 0s, height 0.5s ease-in 0s, top 0.5s ease-out 0s)); }
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/typography/links/hover-link.scss
================================================
@import "compass/typography/links/hover-link";
a { @include hover-link; }
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/units.scss
================================================
$base-font-size: 16px;
@import "compass/typography/units";
.foo {
width: 600px;
height: 200px;
}
.foo .test {
/* 16px for margins should be 1em */
margin-top: convert-length(16px, em);
/* 16px for margins should be 2.66667% (relative to parent's width) */
margin-right: convert-length(16px, '%', $to-context: 600px);
/* 1.35em for margins should be 3.6% (relative to parent's width,
* even for top and bottom margins) */
margin-bottom: convert-length(1.35em, '%', $to-context: 600px);
/* 16px for margins should be 2ex */
margin-left: convert-length(16px, ex);
}
.bar {
font-size: 18px;
width: 360px;
}
.bar .test {
/* 150% for line-height should be 27px */
line-height: convert-length(150%, px, 18px);
/* 1px should always be .0625rem for this page */
border-top: convert-length(1px, rem);
/* 2em for this element should be 9.525mm (relative to own font-size, as inherited) */
margin-top: convert-length(2em, mm, 18px);
/* 2px for margins should be .55556% (relative to parent's width) */
margin-right: convert-length(2px, '%', $to-context: 360px);
/* 1rem should always be 16px for this page, even when own font-size is 18px */
margin-bottom: convert-length(1rem, px);
}
.rem {
$val: 25rem, 100% 32px;
@include rem(background-size, $val, true);
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/user-interface.scss
================================================
@import "compass/css3/user-interface";
.user-select {
@include user-select(none);
}
* {
@include input-placeholder {
color: #bfbfbf;
font-style: italic;
}
}
#{elements-of-type(text-input)} {
@include input-placeholder {
color: #bfbfbf;
font-style: italic;
}
}
.sets-up-browser-support-for-content {
@include input-placeholder {
prefix: $current-prefix;
-moz-prefix: $current-prefix == -moz;
-ms-prefix: $current-prefix == -ms;
-webkit-prefix: $current-prefix == -webkit;
}
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/utilities.scss
================================================
$contrasted-dark-default: black;
$contrasted-light-default: white;
@import "compass/utilities";
.clearfix {
@include clearfix;
}
.pie-clearfix {
@include legacy-pie-clearfix;
}
.simple-pie-clearfix {
@include pie-clearfix;
}
p.light { @include contrasted(#f3aead); }
p.dark { @include contrasted(#a22321); }
p.light-with-args { @include contrasted(#f3aead, blue, yellow); }
p.dark-with-args { @include contrasted(#a22321, blue, yellow); }
@include alternating-rows-and-columns(red, white, blue);
p.ellipsis {
@include ellipsis;
}
p.ellipsis.moz {
$legacy-support-for-mozilla: true !global;
$use-mozilla-ellipsis-binding: true !global;
@include ellipsis;
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/vertical_rhythm.scss
================================================
// Test all functions and mixins, at least indirectly.
// functions:
// * rhythm
// * lines-for-font-size
//
// mixins:
// * establish-baseline
// * output-rhythm
// * debug-vertical-alignment
// * adjust-font-size-to
// * adjust-leading-to
// * leader
// * margin-leader
// * padding-leader
// * trailer
// * margin-trailer
// * padding-trailer
// * rhythm
// * rhythm-margins
// * rhythm-padding
// * apply-side-rhythm-border
// * leading-border
// * trailing-border
// * rhythm-borders
// * horizontal-borders (h-borders)
//
// deprecated mixins:
// * reset-baseline
$base-font-size: 14px;
$base-line-height: 16px;
@import "compass/typography/vertical_rhythm";
@include establish-baseline;
.small {
@include adjust-font-size-to(12px, 1);
}
.padded {
@include rhythm(1, 1, 1, 1);
}
.small-padded {
@include adjust-font-size-to(12px, 1);
@include rhythm(1, 1, 1, 1, 12px);
}
.borders {
@include h-borders(1px, 1);
}
.large-borders {
@include adjust-font-size-to(24px, 3);
@include h-borders(6px, 1, 24px);
}
.reset {
@include reset-baseline;
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/vertical_rhythm_with_ems.scss
================================================
/* New test using em output */
$base-font-size: 18px;
$base-line-height: $base-font-size * 1.4;
$rhythm-unit: em;
$default-rhythm-border-style: solid #aaaaaa;
@import "compass/typography/vertical_rhythm";
@include establish-baseline;
.container {
@include debug-vertical-alignment;
}
p {
@include margin-leader;
@include margin-trailer;
}
th,
td {
@include rhythm-padding(.25);
}
// Incremental leading made easy!
.caption {
@include adjust-font-size-to(13px, 4/5);
}
.spaced-out {
@include adjust-leading-to(1.5);
}
blockquote {
@include rhythm-margins;
padding: 0 rhythm();
}
.fig-quote {
> blockquote {
@include trailer(.5);
}
.source {
@include adjust-font-size-to(13px, auto);
@include trailer(.5, 13px);
}
}
.panel {
@include adjust-font-size-to(16px);
@include rhythm-borders($font-size: 16px);
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/vertical_rhythm_with_px.scss
================================================
/* New using px output */
$base-font-size: 18px;
$base-line-height: $base-font-size * 1.4;
$rhythm-unit: px;
$default-rhythm-border-style: solid #aaaaaa;
@import "compass/typography/vertical_rhythm";
@include establish-baseline;
.container {
@include debug-vertical-alignment;
}
p {
@include margin-leader;
@include margin-trailer;
}
th,
td {
@include rhythm-padding(.25);
}
/* Incremental leading made easy! */
.caption {
@include adjust-font-size-to(.85rem, 4/5);
}
.spaced-out {
@include adjust-leading-to(1.5);
}
blockquote {
@include rhythm-margins;
padding: 0 rhythm();
}
.fig-quote {
> blockquote {
@include trailer(.5);
}
.source {
@include adjust-font-size-to(.85rem, auto);
@include trailer(.5);
}
}
.panel {
@include rhythm-borders;
}
================================================
FILE: cli/test/fixtures/stylesheets/compass/sass/vertical_rhythm_with_rems.scss
================================================
/* New using rem output with pixel fallbacks */
$base-font-size: 18px;
$base-line-height: $base-font-size * 1.4;
$rhythm-unit: rem;
$default-rhythm-border-style: solid #aaaaaa;
@import "compass/typography/vertical_rhythm";
@include establish-baseline;
.container {
@include debug-vertical-alignment;
}
p {
@include margin-leader;
@include margin-trailer;
}
th,
td {
@include rhythm-padding(.25);
}
/* Incremental leading made easy! */
.caption {
@include adjust-font-size-to(.85rem, 4/5);
}
.spaced-out {
@include adjust-leading-to(1.5);
}
blockquote {
@include rhythm-margins;
padding: 0 rhythm();
}
.fig-quote {
> blockquote {
@include trailer(.5);
}
.source {
@include adjust-font-size-to(.85rem, auto);
@include trailer(.5);
}
}
.panel {
@include rhythm-borders;
}
================================================
FILE: cli/test/fixtures/stylesheets/envtest/config.rb
================================================
# Require any additional compass plugins here.
project_type = :stand_alone
css_dir = "tmp"
sass_dir = "sass"
images_dir = "images"
output_style = :nested
line_comments = false
disable_warnings = true
================================================
FILE: cli/test/fixtures/stylesheets/envtest/css/env.css
================================================
.env {
env: <%= options[:environment] %>; }
.time {
time: <%= Time.now.strftime("%F") %>; }
.date {
date: <%= Time.now.strftime("%F") %>; }
.filename {
file: env.scss; }
.output {
output: env.css; }
================================================
FILE: cli/test/fixtures/stylesheets/envtest/sass/env.scss
================================================
.env {
env: compass-env();
}
.time {
time: current-time("%F");
}
.date {
date: current-date("%F");
}
.filename {
file: current-source-file();
}
.output {
output: current-output-file();
}
================================================
FILE: cli/test/fixtures/stylesheets/error/config.rb
================================================
# Require any additional compass plugins here.
css_dir = "tmp"
sass_dir = "sass"
images_dir = "assets/images"
javascripts_dir = "assets/javascripts"
# Set this to the root of your project when deployed:
http_path = "/"
# To enable relative paths to assets via compass helper functions. Uncomment:
output_style = :compact
relative_assets = true
================================================
FILE: cli/test/fixtures/stylesheets/error/sass/screen.sass
================================================
test
background: image_url("testing.png)
================================================
FILE: cli/test/fixtures/stylesheets/image_urls/config.rb
================================================
# Require any additional compass plugins here.
project_type = :stand_alone
css_dir = "tmp"
sass_dir = "sass"
images_dir = "images"
output_style = :compact
# To enable relative image paths using the images_url() function:
# http_images_path = :relative
http_images_path = "/images"
line_comments = false
asset_cache_buster do |path, file|
"busted=true"
end
asset_host do |path|
"http://assets%d.example.com" % (path.size % 4)
end
================================================
FILE: cli/test/fixtures/stylesheets/image_urls/css/screen.css
================================================
.showgrid { background-image: url('http://assets0.example.com/images/grid.png?busted=true'); }
.inlinegrid { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAUEAYAAACv1qP4AAAABmJLR0T///////8JWPfcAAAACXBIWXMAAABIAAAASABGyWs+AAAAZ0lEQVRYw+3QwQ2AIBAFUTEUwI3+uzN7gDscsIgxEuO8An52J11X73OudfxMraXkzHfO3Y98nQEhA0IGhAwIGRAyIGRAyICQASEDQgaEDAgZEDIgZEDIgJABoZzSGK3tPuN9ERFP7Nw4fg+c5g8V1wAAAABJRU5ErkJggg=='); }
.no-buster { background-image: url('http://assets0.example.com/images/grid.png'); }
================================================
FILE: cli/test/fixtures/stylesheets/image_urls/sass/screen.sass
================================================
.showgrid
background-image: image-url(unquote("grid.png"))
.inlinegrid
background-image: inline-image(unquote("grid.png"))
.no-buster
background-image: image-url("grid.png", $only-path: false, $cache-buster: false)
================================================
FILE: cli/test/fixtures/stylesheets/relative/config.rb
================================================
# Require any additional compass plugins here.
css_dir = "tmp"
sass_dir = "sass"
images_dir = "assets/images"
javascripts_dir = "assets/javascripts"
# Set this to the root of your project when deployed:
http_path = "/"
# To enable relative paths to assets via compass helper functions. Uncomment:
output_style = :compact
relative_assets = true
================================================
FILE: cli/test/fixtures/stylesheets/relative/css/ie.css
================================================
/* Welcome to Compass. Use this file to write IE specific override styles. Import this file using the following HTML or equivalent: */
================================================
FILE: cli/test/fixtures/stylesheets/relative/css/print.css
================================================
/* Welcome to Compass. Use this file to define print styles. Import this file using the following HTML or equivalent: */
================================================
FILE: cli/test/fixtures/stylesheets/relative/css/screen.css
================================================
test { background: url('../assets/images/testing.png?<%= File.mtime(File.join(Compass.configuration.project_path, 'assets', 'images', 'testing.png')).strftime("%s") %>'); }
================================================
FILE: cli/test/fixtures/stylesheets/relative/sass/ie.sass
================================================
/* Welcome to Compass. Use this file to write IE specific override styles.
Import this file using the following HTML or equivalent:
================================================
FILE: cli/test/fixtures/stylesheets/relative/sass/print.sass
================================================
/* Welcome to Compass. Use this file to define print styles.
Import this file using the following HTML or equivalent:
================================================
FILE: cli/test/fixtures/stylesheets/relative/sass/screen.sass
================================================
test
background: image_url(unquote("testing.png"))
================================================
FILE: cli/test/fixtures/stylesheets/sourcemaps/config.rb
================================================
# Require any additional compass plugins here.
css_dir = "tmp"
sass_dir = "sass"
images_dir = "assets/images"
javascripts_dir = "assets/javascripts"
# Set this to the root of your project when deployed:
http_path = "/"
# To enable relative paths to assets via compass helper functions. Uncomment:
relative_assets = true
sourcemap = true
================================================
FILE: cli/test/fixtures/stylesheets/sourcemaps/css/another_simple.css
================================================
.another-simple-class{color:blue}
/*# sourceMappingURL=another_simple.css.map */
================================================
FILE: cli/test/fixtures/stylesheets/sourcemaps/css/simple.css
================================================
div{color:red}
/*# sourceMappingURL=simple.css.map */
================================================
FILE: cli/test/fixtures/stylesheets/sourcemaps/css/with_libraries.css
================================================
*{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
/*# sourceMappingURL=with_libraries.css.map */
================================================
FILE: cli/test/fixtures/stylesheets/sourcemaps/sass/another_simple.scss
================================================
.another-simple-class {
color: blue;
}
================================================
FILE: cli/test/fixtures/stylesheets/sourcemaps/sass/simple.sass
================================================
div
color: red
================================================
FILE: cli/test/fixtures/stylesheets/sourcemaps/sass/with_libraries.scss
================================================
@import "compass/css3/box-sizing";
* {
@include box-sizing;
}
================================================
FILE: cli/test/fixtures/stylesheets/uses_only_stylesheets_ext/config.rb
================================================
# Require any additional compass plugins here.
load '../../extensions/only_stylesheets/'
# Set this to the root of your project when deployed:
http_path = "/"
css_dir = "stylesheets"
sass_dir = "sass"
images_dir = "images"
javascripts_dir = "javascripts"
# You can select your preferred output style here (can be overridden via the command line):
# output_style = :expanded or :nested or :compact or :compressed
# To enable relative paths to assets via compass helper functions. Uncomment:
# relative_assets = true
# To disable debugging comments that display the original location of your selectors. Uncomment:
# line_comments = false
# If you prefer the indented syntax, you might want to regenerate this
# project again passing --syntax sass, or you can uncomment this:
# preferred_syntax = :sass
# and then run:
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass
================================================
FILE: cli/test/fixtures/stylesheets/uses_only_stylesheets_ext/sass/ie.scss
================================================
/* Welcome to Compass. Use this file to write IE specific override styles.
* Import this file using the following HTML or equivalent:
* */
================================================
FILE: cli/test/fixtures/stylesheets/uses_only_stylesheets_ext/sass/print.scss
================================================
/* Welcome to Compass. Use this file to define print styles.
* Import this file using the following HTML or equivalent:
* */
================================================
FILE: cli/test/fixtures/stylesheets/uses_only_stylesheets_ext/sass/screen.scss
================================================
/* Welcome to Compass.
* In this file you should write your main styles. (or centralize your imports)
* Import this file using the following HTML or equivalent:
* */
@import "compass/reset";
================================================
FILE: cli/test/fixtures/stylesheets/uses_only_stylesheets_ext/stylesheets/ie.css
================================================
/* Welcome to Compass. Use this file to write IE specific override styles.
* Import this file using the following HTML or equivalent:
* */
================================================
FILE: cli/test/fixtures/stylesheets/uses_only_stylesheets_ext/stylesheets/print.css
================================================
/* Welcome to Compass. Use this file to define print styles.
* Import this file using the following HTML or equivalent:
* */
================================================
FILE: cli/test/fixtures/stylesheets/uses_only_stylesheets_ext/stylesheets/screen.css
================================================
/* Welcome to Compass.
* In this file you should write your main styles. (or centralize your imports)
* Import this file using the following HTML or equivalent:
* */
/* line 17, ../../../../../../../.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/compass-0.12.alpha.0/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* line 20, ../../../../../../../.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/compass-0.12.alpha.0/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
body {
line-height: 1;
}
/* line 22, ../../../../../../../.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/compass-0.12.alpha.0/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
ol, ul {
list-style: none;
}
/* line 24, ../../../../../../../.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/compass-0.12.alpha.0/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
table {
border-collapse: collapse;
border-spacing: 0;
}
/* line 26, ../../../../../../../.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/compass-0.12.alpha.0/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
caption, th, td {
text-align: left;
font-weight: normal;
vertical-align: middle;
}
/* line 28, ../../../../../../../.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/compass-0.12.alpha.0/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
q, blockquote {
quotes: none;
}
/* line 101, ../../../../../../../.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/compass-0.12.alpha.0/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
q:before, q:after, blockquote:before, blockquote:after {
content: "";
content: none;
}
/* line 30, ../../../../../../../.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/compass-0.12.alpha.0/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
a img {
border: none;
}
/* line 114, ../../../../../../../.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/compass-0.12.alpha.0/frameworks/compass/stylesheets/compass/reset/_utilities.scss */
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary {
display: block;
}
================================================
FILE: cli/test/fixtures/stylesheets/valid/config.rb
================================================
# Require any additional compass plugins here.
css_dir = "tmp"
sass_dir = "sass"
images_dir = "assets/images"
javascripts_dir = "assets/javascripts"
# Set this to the root of your project when deployed:
http_path = "/"
# To enable relative paths to assets via compass helper functions. Uncomment:
relative_assets = true
================================================
FILE: cli/test/fixtures/stylesheets/valid/sass/another_simple.scss
================================================
.another-simple-class {
color: blue;
}
================================================
FILE: cli/test/fixtures/stylesheets/valid/sass/simple.sass
================================================
div
color: red
================================================
FILE: cli/test/fixtures/stylesheets/with_sass_globbing/config.rb
================================================
require 'sass-globbing'
require 'compass/import-once/activate'
# Require any additional compass plugins here.
# Set this to the root of your project when deployed:
http_path = "/"
css_dir = "tmp"
sass_dir = "sass"
images_dir = "images"
javascripts_dir = "javascripts"
# You can select your preferred output style here (can be overridden via the command line):
output_style = :expanded
# To enable relative paths to assets via compass helper functions. Uncomment:
relative_assets = true
# To disable debugging comments that display the original location of your selectors. Uncomment:
line_comments = true
# If you prefer the indented syntax, you might want to regenerate this
# project again passing --syntax sass, or you can uncomment this:
# preferred_syntax = :sass
# and then run:
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass
================================================
FILE: cli/test/fixtures/stylesheets/with_sass_globbing/css/screen.css
================================================
/* line 1, ../sass/partials/_1.scss */
.one {
value: 1;
}
/* line 1, ../sass/partials/_2.scss */
.two {
value: 2;
}
/* line 1, ../sass/partials/_3.scss */
.three {
value: 3;
}
/* line 3, ../sass/screen.scss */
.something {
awww: yeah;
}
================================================
FILE: cli/test/fixtures/stylesheets/with_sass_globbing/sass/partials/_1.scss
================================================
.one {
value: 1;
}
================================================
FILE: cli/test/fixtures/stylesheets/with_sass_globbing/sass/partials/_2.scss
================================================
.two {
value: 2;
}
================================================
FILE: cli/test/fixtures/stylesheets/with_sass_globbing/sass/partials/_3.scss
================================================
.three {
value: 3;
}
================================================
FILE: cli/test/fixtures/stylesheets/with_sass_globbing/sass/screen.scss
================================================
@import "partials/*";
.something { awww: yeah; }
================================================
FILE: cli/test/helpers/command_line.rb
================================================
require 'timeout'
module Compass::CommandLineHelper
def compass(*arguments)
options = arguments.last.is_a?(Hash) ? arguments.pop : {}
options[:wait] = 0.25
if block_given?
responder = Responder.new
yield responder
IO.popen("-", "r+") do |io|
if io
#parent process
output = ""
eof_at = nil
while !eof_at || (Time.now - eof_at < options[:wait])
if io.eof?
eof_at ||= Time.now
sleep 0.1
else
eof_at = nil
timeout(1) do
partial_output = io.readpartial(1024)
# puts "))))#{partial_output}((((("
output << partial_output
end
prompt = output.split("\n").last.strip
if response = responder.response_for(prompt)
io.puts response
io.flush
end
end
end
responder.assert_required_responses!
@last_result = decolorize(output)
else
#child process
execute *arguments
end
end
else
@last_error = capture_warning do
@last_result = decolorize(capture_output do
@last_exit_code = execute *arguments
end)
end
end
rescue Timeout::Error
fail "Read from child process timed out"
end
def decolorize(str)
str.gsub(/\e\[\d+m/,'')
end
class Responder
Response = Struct.new(:prompt, :text, :required, :responded)
def initialize
@responses = []
end
def respond_to(prompt, options = {})
@responses << Response.new(prompt, options[:with], options[:required])
end
def response_for(prompt)
response = @responses.detect do |r|
case r.prompt
when Regexp
prompt =~ r.prompt
when String
r.prompt == prompt
end
end
if response
response.responded = true
response.text
end
end
def assert_required_responses!
@responses.each do |response|
if response.required && !response.responded
raise "Prompt not encountered: \"#{response.prompt}\""
end
end
end
end
def assert_action_performed(action, path)
actions_found = []
@last_result.split("\n").each do |line|
line = line.split
return if line.first == action.to_s && line.last == path
actions_found << line.first if line.last == path
end
message = "Action #{action.inspect} was not performed on: #{path}."
message += "The following actions were performed: #{actions_found.map{|a|a.inspect}.join(", ")}" if actions_found.any?
# puts @last_result
fail message
end
def within_tmp_directory(dir = "tmp")
d = absolutize(dir)
FileUtils.mkdir_p(d)
Dir.chdir(d) do
yield
end
ensure
FileUtils.rm_rf(d)
end
def execute(*arguments)
exit_code = Compass::Exec::SubCommandUI.new(arguments).run!
# fail "Command Failed with exit code: #{exit_code}" unless exit_code == 0
exit_code
end
end
================================================
FILE: cli/test/helpers/diff.rb
================================================
require 'diff/lcs'
require 'diff/lcs/hunk'
module Compass
module Diff
#stole this from rspec who stole this from the gem
def diff_as_string(data_old, data_new)
data_old = data_old.split(/\n/).map! { |e| e.chomp }
data_new = data_new.split(/\n/).map! { |e| e.chomp }
output = ""
diffs = ::Diff::LCS.diff(data_old, data_new)
return output if diffs.empty?
oldhunk = hunk = nil
file_length_difference = 0
diffs.each do |piece|
begin
hunk = ::Diff::LCS::Hunk.new(
data_old, data_new, piece, context_lines, file_length_difference
)
file_length_difference = hunk.file_length_difference
next unless oldhunk
# Hunks may overlap, which is why we need to be careful when our
# diff includes lines of context. Otherwise, we might print
# redundant lines.
if (context_lines > 0) and hunk.overlaps?(oldhunk)
hunk.unshift(oldhunk)
else
output << oldhunk.diff(format)
end
ensure
oldhunk = hunk
output << "\n"
end
end
#Handle the last remaining hunk
output << oldhunk.diff(format) << "\n"
end
protected
def format
:unified
end
def context_lines
3
end
end
end
================================================
FILE: cli/test/helpers/io.rb
================================================
module Compass
module IoHelper
def capture_output
real_stdout, $stdout = $stdout, StringIO.new
yield
$stdout.string
ensure
$stdout = real_stdout
end
def capture_warning
real_stderr, $stderr = $stderr, StringIO.new
yield
$stderr.string
ensure
$stderr = real_stderr
end
def capture_pipe(io, options = {})
options[:wait] = 0.25
options[:timeout] = 1.0
output = ""
eof_at = nil
while !eof_at || (Time.now - eof_at < options[:wait])
if io.eof?
eof_at ||= Time.now
sleep 0.1
else
eof_at = nil
timeout(options[:timeout]) { output << io.readpartial(1024) }
end
end
output
end
end
end
================================================
FILE: cli/test/helpers/rails.rb
================================================
module Compass
module RailsHelper
def generate_rails_app_directories(name)
Dir.mkdir name
Dir.mkdir File.join(name, "config")
Dir.mkdir File.join(name, "config", "initializers")
Dir.mkdir File.join(name, "tmp")
end
# Generate a rails application without polluting our current set of requires
# with the rails libraries. This will allow testing against multiple versions of rails
# by manipulating the load path.
def generate_rails_app(name, dir = nil)
if pid = fork
Process.wait(pid)
if $?.exitstatus == 2
raise LoadError, "Couldn't load rails"
elsif $?.exitstatus != 0
raise "Failed to generate rails application."
end
else
begin
require 'action_pack/version'
if ActionPack::VERSION::MAJOR >= 3
require 'rails/generators'
require 'rails/generators/rails/app/app_generator'
require 'mocha'
dir ||= File.join(File.expand_path('../../', __FILE__))
args = [File.join(dir, name), '-q', '-f', '--skip-bundle', '--skip-gemfile']
#stub this so you can generate more apps
Rails::Generators::AppGenerator.any_instance.stubs(:valid_const?).returns(true)
Rails::Generators::AppGenerator.start(args, {:destination_root => dir})
else
require 'rails/version'
require 'rails_generator'
require 'rails_generator/scripts/generate'
Rails::Generator::Base.use_application_sources!
capture_output do
Rails::Generator::Base.logger = Rails::Generator::SimpleLogger.new $stdout
Rails::Generator::Scripts::Generate.new.run([name], :generator => 'app')
end
end
rescue LoadError
Kernel.exit!(2)
rescue => e
$stderr.puts e
Kernel.exit!(1)
end
Kernel.exit!(0)
end
end
end
end
================================================
FILE: cli/test/helpers/test_case.rb
================================================
module Compass
module TestCaseHelper
def absolutize(path)
if Compass::Util.blank?(path)
File.expand_path('../../', __FILE__)
elsif path[0] == ?/
File.join(File.expand_path('../', __FILE__), path)
else
File.join(File.expand_path('../../', __FILE__), path)
end
end
# compile a Sass string in the context of a project in the current working directory.
def compile_for_project(contents, options = {})
Compass.add_project_configuration
options[:syntax] ||= :scss
Sass::Engine.new(contents, Compass.configuration.to_sass_engine_options.merge(options)).render
end
def assert_correct(before, after)
if before == after
assert(true)
else
assert false, diff_as_string(before.inspect, after.inspect)
end
end
module ClassMethods
def let(method, &block)
define_method method, &block
end
def it(name, &block)
test(name, &block)
end
def test(name, &block)
define_method "test_#{underscore(name)}".to_sym, &block
end
def setup(&block)
define_method :setup do
yield
end
end
def after(&block)
define_method :teardown do
yield
end
end
private
def underscore(string)
string.gsub(' ', '_')
end
end
end
end
================================================
FILE: cli/test/integrations/compass_test.rb
================================================
require 'test_helper'
require 'fileutils'
require 'compass'
require 'compass/logger'
require 'sass/plugin'
class CompassTest < Test::Unit::TestCase
def setup
Compass.reset_configuration!
end
def teardown
Dir.glob(absolutize("fixtures/stylesheets/*")).each do |dir|
project_name = File.basename(dir)
::FileUtils.rm_rf tempfile_path(project_name)
::FileUtils.rm_rf File.join(project_path(project_name), ".sass-cache")
end
end
def test_on_stylesheet_saved_callback
saved = false
path = nil
config = nil
before_compile = Proc.new do |config|
config.on_stylesheet_saved {|filepath| path = filepath; saved = true }
end
within_project(:compass, before_compile)
assert saved, "Stylesheet callback didn't get called"
assert path.is_a?(String), "Path is not a string. Got: #{path.class.name}"
end
# no project with errors exists to test aginst - leep of FAITH!
# *chriseppstein flogs himself*
def test_on_stylesheet_error_callback
error = false
file = nil
before_compile = Proc.new do |config|
config.on_stylesheet_error {|filename, message| file = filename; error = true }
end
within_project(:error, before_compile) rescue nil
assert error, "Project did not throw a compile error"
assert file.is_a?(String), "Filename was not a string"
end
def test_empty_project
# With no sass files, we should have no css files.
within_project(:empty) do |proj|
return unless proj.css_path && File.exists?(proj.css_path)
Dir.new(proj.css_path).each do |f|
fail "This file should not have been generated: #{f}" unless f == "." || f == ".."
end
end
end
def test_compass
within_project('compass') do |proj|
each_css_file(proj.css_path) do |css_file|
assert_no_errors css_file, 'compass'
end
each_sass_file do |sass_file|
assert_renders_correctly sass_file, :ignore_charset => true
end
end
end
def test_sourcemaps
within_project('sourcemaps') do |proj|
each_css_file(proj.css_path) do |css_file|
assert_no_errors css_file, 'sourcemaps'
end
each_sass_file do |sass_file|
assert_renders_correctly sass_file, :ignore_charset => true
end
end
end
def test_env_in_development
within_project('envtest', lambda {|c| c.environment = :development }) do |proj|
each_css_file(proj.css_path) do |css_file|
assert_no_errors css_file, 'envtest'
end
each_sass_file do |sass_file|
assert_renders_correctly sass_file, :ignore_charset => true, :environment => "development"
end
end
end
def test_env_in_production
within_project('envtest', lambda {|c| c.environment = :production }) do |proj|
each_css_file(proj.css_path) do |css_file|
assert_no_errors css_file, 'envtest'
end
each_sass_file do |sass_file|
assert_renders_correctly sass_file, :ignore_charset => true, :environment => "production"
end
end
end
def test_busted_font_urls
within_project('busted_font_urls') do |proj|
each_css_file(proj.css_path) do |css_file|
assert_no_errors css_file, 'busted_font_urls'
end
each_sass_file do |sass_file|
assert_renders_correctly sass_file
end
end
end
def test_busted_image_urls
within_project('busted_image_urls') do |proj|
each_css_file(proj.css_path) do |css_file|
assert_no_errors css_file, 'busted_image_urls'
end
each_sass_file do |sass_file|
assert_renders_correctly sass_file
end
end
end
def test_with_sass_globbing
within_project('with_sass_globbing') do |proj|
each_css_file(proj.css_path) do |css_file|
assert_no_errors css_file, 'with_sass_globbing'
end
each_sass_file do |sass_file|
assert_renders_correctly sass_file
end
end
end
def test_image_urls
within_project('image_urls') do |proj|
each_css_file(proj.css_path) do |css_file|
assert_no_errors css_file, 'image_urls'
end
each_sass_file do |sass_file|
assert_renders_correctly sass_file
end
end
end
def test_relative
within_project('relative') do |proj|
each_css_file(proj.css_path) do |css_file|
assert_no_errors css_file, 'relative'
end
each_sass_file do |sass_file|
assert_renders_correctly sass_file
end
end
end
private
def assert_no_errors(css_file, project_name)
file = css_file[(tempfile_path(project_name).size+1)..-1]
msg = "Syntax Error found in #{file}. Results saved into #{save_path(project_name)}/#{file}"
assert_equal 0, open(css_file).readlines.grep(/Sass::SyntaxError/).size, msg
end
def assert_renders_correctly(*arguments)
options = arguments.last.is_a?(Hash) ? arguments.pop : {}
for name in arguments
@output_file = actual_result_file = "#{tempfile_path(@current_project)}/#{name}.css"
expected_result_file = "#{result_path(@current_project)}/#{name}.css"
@filename = expected_result_file.gsub('css', 'scss')
actual_lines = File.read(actual_result_file)
actual_lines.gsub!(/^@charset[^;]+;/,'') if options[:ignore_charset]
actual_lines = actual_lines.split("\n").reject{|l| l=~/\A\Z/}
expected_lines = ERB.new(File.read(expected_result_file)).result(binding)
expected_lines.gsub!(/^@charset[^;]+;/,'') if options[:ignore_charset]
expected_lines = expected_lines.split("\n").reject{|l| l=~/\A\Z/}
expected_lines.zip(actual_lines).each_with_index do |pair, line|
if pair.first == pair.last
assert(true)
else
assert false, "Error in #{result_path(@current_project)}/#{name}.css:#{line + 1}\n"+diff_as_string(pair.first.inspect, pair.last.inspect)
end
end
if expected_lines.size < actual_lines.size
assert(false, "#{actual_lines.size - expected_lines.size} Trailing lines found in #{actual_result_file}: #{actual_lines[expected_lines.size..-1].join('\n')}")
end
end
end
def within_project(project_name, config_block = nil)
@current_project = project_name
Compass.add_configuration(configuration_file(project_name)) if File.exists?(configuration_file(project_name))
Compass.configuration.project_path = project_path(project_name)
Compass.configuration.environment = :production
Compass.configuration.sourcemap = false unless Compass.configuration.sourcemap_set?
if config_block
config_block.call(Compass.configuration)
end
if Compass.configuration.sass_path && File.exists?(Compass.configuration.sass_path)
compiler = Compass.sass_compiler
compiler.logger = Compass::NullLogger.new
compiler.clean!
compiler.compile!
end
yield Compass.configuration if block_given?
rescue
save_output(project_name)
raise
end
def each_css_file(dir, &block)
Dir.glob("#{dir}/**/*.css").each(&block)
end
def each_sass_file(sass_dir = nil)
sass_dir ||= template_path(@current_project)
Dir.glob("#{sass_dir}/**/*.s[ac]ss").each do |sass_file|
next if File.basename(sass_file).start_with?("_")
yield sass_file[(sass_dir.length+1)..-6]
end
end
def save_output(dir)
FileUtils.rm_rf(save_path(dir))
FileUtils.cp_r(tempfile_path(dir), save_path(dir)) if File.exists?(tempfile_path(dir))
end
def project_path(project_name)
absolutize("fixtures/stylesheets/#{project_name}")
end
def configuration_file(project_name)
File.join(project_path(project_name), "config.rb")
end
def tempfile_path(project_name)
File.join(project_path(project_name), "tmp")
end
def template_path(project_name)
File.join(project_path(project_name), "sass")
end
def result_path(project_name)
File.join(project_path(project_name), "css")
end
def save_path(project_name)
File.join(project_path(project_name), "saved")
end
def filename
@filename
end
def output_file
@output_file
end
end
================================================
FILE: cli/test/integrations/sprites_test.rb
================================================
require 'test_helper'
require 'fileutils'
require 'compass'
require 'compass/logger'
require 'sass/plugin'
class SpritesTest < Test::Unit::TestCase
def setup
Compass.reset_configuration!
@images_project_path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'fixtures', 'sprites', 'public'))
@images_src_dir = 'images'
@images_src_path = File.join(@images_project_path, @images_src_dir)
@images_tmp_dir = 'images-tmp'
@images_tmp_path = File.join(@images_project_path, @images_tmp_dir)
@generated_images_tmp_dir = 'generated-images-tmp'
@generated_images_tmp_path = File.join(@images_project_path, @generated_images_tmp_dir)
::FileUtils.cp_r @images_src_path, @images_tmp_path
::FileUtils.mkdir_p @generated_images_tmp_path
file = StringIO.new(<<-CONFIG)
project_path = "#{@images_project_path}"
images_dir = "#{@images_tmp_dir}"
CONFIG
Compass.add_configuration(file, "sprite_config")
Compass.configure_sass_plugin!
end
def teardown
Compass.reset_configuration!
::FileUtils.rm_r @images_tmp_path
::FileUtils.rm_rf @generated_images_tmp_path
end
def map_location(file)
map_files(file).first
end
def map_files(glob)
Dir.glob(File.join(@images_tmp_path, glob))
end
def image_size(file)
Compass::Core::SassExtensions::Functions::ImageSize::ImageProperties.new(map_location(file)).size
end
def image_md5(file)
md5 = Digest::MD5.new
md5.update IO.read(map_location(file))
md5.hexdigest
end
def render(scss)
options = Compass.sass_engine_options
options[:line_comments] = false
options[:style] = :expanded
options[:syntax] = :scss
options[:compass] ||= {}
options[:compass][:logger] ||= Compass::NullLogger.new
css = Sass::Engine.new(scss, options).render
# reformat to fit result of heredoc:
" #{css.gsub('@charset "UTF-8";', '').gsub(/\n/, "\n ").strip}\n"
end
def clean(string)
string.gsub("\n", '').gsub(' ', '')
end
it "should generate sprite classes" do
css = render <<-SCSS
@import "squares/*.png";
@include all-squares-sprites;
SCSS
assert_correct <<-CSS, css
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background-image: url('/images-tmp/squares-sbbc18e2129.png');
background-repeat: no-repeat;
}
.squares-ten-by-ten {
background-position: 0 0;
}
.squares-twenty-by-twenty {
background-position: 0 -10px;
}
CSS
assert_equal image_size('squares-s*.png'), [20, 30]
assert_equal image_md5('squares-s*.png'), '7349a0f4e88ea80abddcf6ac2486abe3'
end
it "should output and serve sprite files using the generated images directory" do
Compass.reset_configuration!
file = StringIO.new(<<-CONFIG)
images_path = #{@images_tmp_path.inspect}
generated_images_path = #{@generated_images_tmp_path.inspect}
http_generated_images_path = "/images/generated"
CONFIG
Compass.add_configuration(file, "sprite_config")
Compass.configure_sass_plugin!
css = render <<-SCSS
@import "squares/*.png";
@include all-squares-sprites;
SCSS
assert_not_nil Dir.glob("#{@generated_images_tmp_path}/squares-s*.png").first
assert_correct <<-CSS, css
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background-image: url('/images/generated/squares-sbbc18e2129.png');
background-repeat: no-repeat;
}
.squares-ten-by-ten {
background-position: 0 0;
}
.squares-twenty-by-twenty {
background-position: 0 -10px;
}
CSS
end
it "should generate sprite classes with dimensions" do
css = render <<-SCSS
$squares-sprite-dimensions: true;
@import "squares/*.png";
@include all-squares-sprites;
SCSS
assert_correct <<-CSS, css
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background-image: url('/images-tmp/squares-sbbc18e2129.png');
background-repeat: no-repeat;
}
.squares-ten-by-ten {
background-position: 0 0;
height: 10px;
width: 10px;
}
.squares-twenty-by-twenty {
background-position: 0 -10px;
height: 20px;
width: 20px;
}
CSS
assert_equal image_size('squares-s*.png'), [20, 30]
end
it "should provide sprite mixin" do
css = render <<-SCSS
@import "squares/*.png";
.cubicle {
@include squares-sprite("ten-by-ten");
}
.large-cube {
@include squares-sprite("twenty-by-twenty", true);
}
SCSS
assert_correct <<-CSS, css
.squares-sprite, .cubicle, .large-cube {
background-image: url('/images-tmp/squares-sbbc18e2129.png');
background-repeat: no-repeat;
}
.cubicle {
background-position: 0 0;
}
.large-cube {
background-position: 0 -10px;
height: 20px;
width: 20px;
}
CSS
assert_equal image_size('squares-s*.png'), [20, 30]
end
# CUSTOMIZATIONS:
it "should be possible to change the base class" do
css = render <<-SCSS
$squares-sprite-base-class: ".circles";
@import "squares/*.png";
SCSS
assert_correct <<-CSS, css
.circles {
background-image: url('/images-tmp/squares-sbbc18e2129.png');
background-repeat: no-repeat;
}
CSS
assert_equal image_size('squares-s*.png'), [20, 30]
end
it "should calculate the spacing between images but not before first image" do
css = render <<-SCSS
$squares-ten-by-ten-spacing: 33px;
@import "squares/*.png";
@include all-squares-sprites;
SCSS
assert_correct <<-CSS, css
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background-image: url('/images-tmp/squares-s563a5e0855.png');
background-repeat: no-repeat;
}
.squares-ten-by-ten {
background-position: 0 0;
}
.squares-twenty-by-twenty {
background-position: 0 -43px;
}
CSS
assert_equal image_size('squares-s*.png'), [20, 63]
end
it "should calculate the spacing between images" do
css = render <<-SCSS
$squares-twenty-by-twenty-spacing: 33px;
@import "squares/*.png";
@include all-squares-sprites;
SCSS
assert_correct <<-CSS, css
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background-image: url('/images-tmp/squares-s4ea353fa6d.png');
background-repeat: no-repeat;
}
.squares-ten-by-ten {
background-position: 0 0;
}
.squares-twenty-by-twenty {
background-position: 0 -43px;
}
CSS
assert_equal image_size('squares-s*.png'), [20, 63]
end
it "should calculate the maximum spacing between images" do
css = render <<-SCSS
$squares-ten-by-ten-spacing: 44px;
$squares-twenty-by-twenty-spacing: 33px;
@import "squares/*.png";
@include all-squares-sprites;
SCSS
assert_correct <<-CSS, css
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background-image: url('/images-tmp/squares-sf4771cb124.png');
background-repeat: no-repeat;
}
.squares-ten-by-ten {
background-position: 0 0;
}
.squares-twenty-by-twenty {
background-position: 0 -54px;
}
CSS
assert_equal image_size('squares-s*.png'), [20, 74]
end
it "should calculate the maximum spacing between images in reversed order" do
css = render <<-SCSS
$squares-ten-by-ten-spacing: 33px;
$squares-twenty-by-twenty-spacing: 44px;
@import "squares/*.png";
@include all-squares-sprites;
SCSS
assert_correct <<-CSS, css
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background-image: url('/images-tmp/squares-sc82d6f3cf4.png');
background-repeat: no-repeat;
}
.squares-ten-by-ten {
background-position: 0 0;
}
.squares-twenty-by-twenty {
background-position: 0 -54px;
}
CSS
assert_equal image_size('squares-s*.png'), [20, 74]
end
it "should calculate the default spacing between images" do
css = render <<-SCSS
$squares-spacing: 22px;
@import "squares/*.png";
@include all-squares-sprites;
SCSS
assert_correct <<-CSS, css
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background-image: url('/images-tmp/squares-s2f4aa65dcf.png');
background-repeat: no-repeat;
}
.squares-ten-by-ten {
background-position: 0 0;
}
.squares-twenty-by-twenty {
background-position: 0 -32px;
}
CSS
assert_equal image_size('squares-s*.png'), [20, 52]
end
it "should use position adjustments in functions" do
css = render <<-SCSS
$squares: sprite-map("squares/*.png", $position: 100%);
.squares-sprite {
background-image: $squares;
background-repeat: no-repeat;
}
.adjusted-percentage {
background-position: sprite-position($squares, ten-by-ten, 100%);
}
.adjusted-px-1 {
background-position: sprite-position($squares, ten-by-ten, 4px);
}
.adjusted-px-2 {
background-position: sprite-position($squares, twenty-by-twenty, -3px, 2px);
}
SCSS
assert_correct <<-CSS, css
.squares-sprite {
background-image: url('/images-tmp/squares-sce5dc30797.png');
background-repeat: no-repeat;
}
.adjusted-percentage {
background-position: 100% 0;
}
.adjusted-px-1 {
background-position: -6px 0;
}
.adjusted-px-2 {
background-position: -3px -8px;
}
CSS
assert_equal image_size('squares-s*.png'), [20, 30]
assert_equal image_md5('squares-s*.png'), '9cc7ce48cfaf304381c2d08adefd2fb6'
end
it "should use position adjustments in mixins" do
css = render <<-SCSS
$squares-position: 100%;
@import "squares/*.png";
.adjusted-percentage {
@include squares-sprite("ten-by-ten", $offset-x: 100%);
}
.adjusted-px-1 {
@include squares-sprite("ten-by-ten", $offset-x: 4px);
}
.adjusted-px-2 {
@include squares-sprite("twenty-by-twenty", $offset-x: -3px, $offset-y: 2px);
}
SCSS
assert_correct <<-CSS, css
.squares-sprite, .adjusted-percentage, .adjusted-px-1, .adjusted-px-2 {
background-image: url('/images-tmp/squares-sce5dc30797.png');
background-repeat: no-repeat;
}
.adjusted-percentage {
background-position: 100% 0;
}
.adjusted-px-1 {
background-position: -6px 0;
}
.adjusted-px-2 {
background-position: -3px -8px;
}
CSS
assert_equal image_size('squares-s*.png'), [20, 30]
assert_equal image_md5('squares-s*.png'), '9cc7ce48cfaf304381c2d08adefd2fb6'
end
it "should repeat the image" do
css = render <<-SCSS
$squares-repeat: repeat-x;
@import "squares/*.png";
@include all-squares-sprites;
SCSS
assert_correct <<-CSS, css
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background-image: url('/images-tmp/squares-s65c43cd573.png');
background-repeat: no-repeat;
}
.squares-ten-by-ten {
background-position: 0 0;
}
.squares-twenty-by-twenty {
background-position: 0 -10px;
}
CSS
assert_equal image_size('squares-s*.png'), [20, 30]
assert_equal image_md5('squares-s*.png'), 'a77a2fd43f04d791722b706aa7c9f1c1'
end
it "should allow the position of a sprite to be specified in absolute pixels" do
css = render <<-SCSS
$squares-ten-by-ten-position: 10px;
$squares-twenty-by-twenty-position: 10px;
@import "squares/*.png";
@include all-squares-sprites;
SCSS
assert_correct <<-CSS, css
.squares-sprite, .squares-ten-by-ten, .squares-twenty-by-twenty {
background-image: url('/images-tmp/squares-sb9d9a8ca6a.png');
background-repeat: no-repeat;
}
.squares-ten-by-ten {
background-position: -10px 0;
}
.squares-twenty-by-twenty {
background-position: -10px -10px;
}
CSS
assert_equal image_size('squares-s*.png'), [30, 30]
assert_equal image_md5('squares-s*.png'), '9856ced9e8211b6b28ff782019a0d905'
end
it "should provide a nice errors for lemonade's old users" do
assert_raise(Sass::SyntaxError) do
render <<-SCSS
.squares {
background-image: sprite-url("squares/*.png");
background-repeat: no-repeat;
}
SCSS
end
assert_raise(Sass::SyntaxError) do
css = render <<-SCSS
@import "squares/*.png";
.squares {
background-image: sprite-position("squares/twenty-by-twenty.png");
background-repeat: no-repeat;
}
SCSS
end
end
it "should work even if @import is missing" do
css = render <<-SCSS
.squares {
background-image: sprite(sprite-map("squares/*.png"), twenty-by-twenty);
background-repeat: no-repeat;
}
SCSS
assert_correct <<-CSS, css
.squares {
background-image: url('/images-tmp/squares-sd817b59156.png') 0 -10px;
background-repeat: no-repeat;
}
CSS
end
it "should import sprites with numeric filenames via #738" do
css = render <<-SCSS
@import "numeric/*.png";
@include all-numeric-sprites;
SCSS
assert_correct <<-CSS, css
.numeric-sprite, .numeric-200 {
background-image: url('/images-tmp/numeric-saa92d65a89.png');
background-repeat: no-repeat;
}
.numeric-200 {
background-position: 0 0;
}
CSS
end
it "should use percentage positions when use_percentages is true" do
css = render <<-SCSS
@import "squares/*.png";
$squares-use-percentages: true;
.foo {
@include squares-sprite-position("twenty-by-twenty");
}
.bar {
@include squares-sprite-position("ten-by-ten");
@include squares-sprite-dimensions("ten-by-ten");
}
SCSS
assert_correct <<-CSS, css
.squares-sprite {
background-image: url('/images-tmp/squares-sbbc18e2129.png');
background-repeat: no-repeat;
}
.foo {
background-position: 0 100%;
}
.bar {
background-position: 0 0;
height: 10px;
width: 10px;
}
CSS
end
it "should use correct percentages when use_percentages is with horizontal layout" do
css = render <<-SCSS
$squares-layout: horizontal;
@import "squares/*.png";
$squares-use-percentages: true;
.foo {
@include squares-sprite-position("twenty-by-twenty");
}
.bar {
@include squares-sprite-position("ten-by-ten");
}
SCSS
assert_correct <<-CSS, css
.squares-sprite {
background-image: url('/images-tmp/squares-s4bd95c5c56.png');
background-repeat: no-repeat;
}
.foo {
background-position: 100% 0;
}
.bar {
background-position: 0 0;
}
CSS
end
it "should use correct percentages when use_percentages is true with smart layout" do
css = render <<-SCSS
$image_row-layout: smart;
@import "image_row/*.png";
$image_row-use-percentages: true;
.foo {
@include image_row-sprite-position("medium");
}
.bar {
@include image_row-sprite-position("large_square");
}
SCSS
assert_correct <<-CSS, css
.image_row-sprite {
background-image: url('/images-tmp/image_row-sc5082a6b9f.png');
background-repeat: no-repeat;
}
.foo {
background-position: 0 50%;
}
.bar {
background-position: 33.33333% 100%;
}
CSS
end
it "should use correct percentages when use_percentages is true" do
css = render <<-SCSS
$image_row-use-percentages: true;
$image_row-sort-by : '!width';
@import "image_row/*.png";
@include all-image_row-sprites;
SCSS
assert_correct <<-CSS, css
.image_row-sprite, .image_row-large, .image_row-large_square, .image_row-medium, .image_row-small, .image_row-tall {
background-image: url('/images-tmp/image_row-sdf383d45a3.png');
background-repeat: no-repeat;
}
.image_row-large {
background-position: 0 0;
}
.image_row-large_square {
background-position: 0 40%;
}
.image_row-medium {
background-position: 0 16.66667%;
}
.image_row-small {
background-position: 0 100%;
}
.image_row-tall {
background-position: 0 80%;
}
CSS
end
it "should calculate corret sprite demsions when givin spacing via issue#253" do
css = render <<-SCSS
$squares-spacing: 10px;
@import "squares/*.png";
.foo {
@include sprite-background-position($squares-sprites, "twenty-by-twenty");
}
.bar {
@include sprite-background-position($squares-sprites, "ten-by-ten");
}
SCSS
assert_equal image_size('squares-s*.png'), [20, 40]
assert_correct <<-CSS, css
.squares-sprite {
background-image: url('/images-tmp/squares-s555875d730.png');
background-repeat: no-repeat;
}
.foo {
background-position: 0 -20px;
}
.bar {
background-position: 0 0;
}
CSS
end
it "should render correct sprite with css selectors via issue#248" do
css = render <<-SCSS
@import "selectors/*.png";
@include all-selectors-sprites;
SCSS
assert_correct <<-CSS, css
.selectors-sprite, .selectors-ten-by-ten {
background-image: url('/images-tmp/selectors-s7e84acb3d2.png');
background-repeat: no-repeat;
}
.selectors-ten-by-ten {
background-position: 0 0;
}
.selectors-ten-by-ten:hover, .selectors-ten-by-ten.ten-by-ten-hover {
background-position: 0 -20px;
}
.selectors-ten-by-ten:target, .selectors-ten-by-ten.ten-by-ten-target {
background-position: 0 -30px;
}
.selectors-ten-by-ten:active, .selectors-ten-by-ten.ten-by-ten-active {
background-position: 0 -10px;
}
CSS
end
it "should honor offsets when rendering selectors via issue#449" do
css = render <<-SCSS
@import "selectors/*.png";
@include all-selectors-sprites($offset-x: 20px, $offset-y: 20px);
SCSS
assert_correct <<-CSS, css
.selectors-sprite, .selectors-ten-by-ten {
background-image: url('/images-tmp/selectors-s7e84acb3d2.png');
background-repeat: no-repeat;
}
.selectors-ten-by-ten {
background-position: 20px 20px;
}
.selectors-ten-by-ten:hover, .selectors-ten-by-ten.ten-by-ten-hover {
background-position: 20px 0;
}
.selectors-ten-by-ten:target, .selectors-ten-by-ten.ten-by-ten-target {
background-position: 20px -10px;
}
.selectors-ten-by-ten:active, .selectors-ten-by-ten.ten-by-ten-active {
background-position: 20px 10px;
}
CSS
end
it "should render correct sprite with css selectors via magic mixin" do
css = render <<-SCSS
@import "selectors/*.png";
a {
@include selectors-sprite(ten-by-ten)
}
SCSS
assert_correct <<-CSS, css
.selectors-sprite, a {
background-image: url('/images-tmp/selectors-s7e84acb3d2.png');
background-repeat: no-repeat;
}
a {
background-position: 0 0;
}
a:hover, a.ten-by-ten-hover {
background-position: 0 -20px;
}
a:target, a.ten-by-ten-target {
background-position: 0 -30px;
}
a:active, a.ten-by-ten-active {
background-position: 0 -10px;
}
CSS
end
it "should not render corret sprite with css selectors via magic mixin" do
css = render <<-SCSS
@import "selectors/*.png";
a {
$disable-magic-sprite-selectors:true !global;
@include selectors-sprite(ten-by-ten)
}
SCSS
assert_correct <<-CSS, css
.selectors-sprite, a {
background-image: url('/images-tmp/selectors-s7e84acb3d2.png');
background-repeat: no-repeat;
}
a {
background-position: 0 0;
}
CSS
end
it "should render corret sprite with css selectors via magic mixin with the correct offsets" do
css = render <<-SCSS
@import "selectors/*.png";
a {
@include selectors-sprite(ten-by-ten, false, 5, -5)
}
SCSS
assert_correct <<-CSS, css
.selectors-sprite, a {
background-image: url('/images-tmp/selectors-s7e84acb3d2.png');
background-repeat: no-repeat;
}
a {
background-position: 5px -5px;
}
a:hover, a.ten-by-ten-hover {
background-position: 5px -25px;
}
a:target, a.ten-by-ten-target {
background-position: 5px -35px;
}
a:active, a.ten-by-ten-active {
background-position: 5px -15px;
}
CSS
end
it "should not raise error on filenames that are invalid classnames if the selector generation is not used" do
css = render <<-SCSS
$prefix-sort-by : 'width';
@import "prefix/*.png";
a {
@include prefix-sprite("20-by-20");
}
SCSS
assert_correct <<-CSS, css
.prefix-sprite, a {
background-image: url('/images-tmp/prefix-s949dea513d.png');
background-repeat: no-repeat;
}
a {
background-position: 0 -10px;
}
CSS
end
it "should generate sprite with bad repeat-x dimensions" do
css = render <<-SCSS
$ko-starbg26x27-repeat: repeat-x;
@import "ko/*.png";
@include all-ko-sprites;
SCSS
assert_correct <<-CSS, css
.ko-sprite, .ko-default_background, .ko-starbg26x27 {
background-image: url('/images-tmp/ko-sd46dfbab4f.png');
background-repeat: no-repeat;
}
.ko-default_background {
background-position: 0 0;
}
.ko-starbg26x27 {
background-position: 0 -128px;
}
CSS
end
it "should generate a sprite and remove the old file" do
FileUtils.touch File.join(@images_tmp_path, "selectors-scc8834Fdd.png")
assert_equal 1, map_files('selectors-s*.png').size
css = render <<-SCSS
@import "selectors/*.png";
a {
$disable-magic-sprite-selectors:true !global;
@include selectors-sprite(ten-by-ten)
}
SCSS
assert_equal 1, map_files('selectors-s*.png').size, "File was not removed"
end
it "should generate a sprite and NOT remove the old file" do
FileUtils.touch File.join(@images_tmp_path, "selectors-scc8834Ftest.png")
assert_equal 1, map_files('selectors-s*.png').size
css = render <<-SCSS
$selectors-clean-up: false;
@import "selectors/*.png";
a {
$disable-magic-sprite-selectors:true !global;
@include selectors-sprite(ten-by-ten)
}
SCSS
assert_equal 2, map_files('selectors-s*.png').size, "File was removed"
end
it "should generate a sprite if the sprite is a bool" do
css = render <<-SCSS
@import "bool/*.png";
a {
@include bool-sprite(false);
}
a {
@include bool-sprite(true);
}
SCSS
assert !css.empty?
end
it "should generate a sprite if the sprite is a colorname" do
css = render <<-SCSS
@import "colors/*.png";
a {
@include colors-sprite(blue);
}
SCSS
assert !css.empty?
end
it "should generate a sprite from nested folders" do
css = render <<-SCSS
@import "nested/**/*.png";
@include all-nested-sprites;
SCSS
assert_correct <<-CSS, css
.nested-sprite, .nested-ten-by-ten {
background-image: url('/images-tmp/nested-s7b93e0b6bf.png');
background-repeat: no-repeat;
}
.nested-ten-by-ten {
background-position: 0 0;
}
CSS
end
it "should create horizontal sprite" do
css = render <<-SCSS
$squares-layout:horizontal;
@import "squares/*.png";
.foo {
@include sprite-background-position($squares-sprites, "twenty-by-twenty");
}
.bar {
@include sprite-background-position($squares-sprites, "ten-by-ten");
}
SCSS
assert_equal [30, 20], image_size('squares-s*.png')
other_css = <<-CSS
.squares-sprite {
background-image: url('/images-tmp/squares-s4bd95c5c56.png');
background-repeat: no-repeat;
}
.foo {
background-position: -10px 0;
}
.bar {
background-position: 0 0;
}
CSS
assert_correct clean(other_css), clean(css)
end
it "should allow use of demension functions" do
css = render <<-SCSS
@import "squares/*.png";
$h: squares-sprite-height(twenty-by-twenty);
$w: squares-sprite-width(twenty-by-twenty);
.div {
height:$h + 1px;
width:$w + 2px;
}
SCSS
other_css = <<-CSS
.squares-sprite {
background-image: url('/images-tmp/squares-sbbc18e2129.png');
background-repeat: no-repeat;
}
.div {
height:21px;
width:22px;
}
CSS
assert_correct clean(other_css), clean(css)
end
it "should replace text with images and dimensions using sprites" do
css = render <<-SCSS
@import "compass/utilities/sprites/sprite-img";
@import "colors/*.png";
.blue {
@include sprite-replace-text($colors-sprites, blue);
}
.yellow {
@include sprite-replace-text-with-dimensions($colors-sprites, yellow);
}
SCSS
other_css = <<-CSS
.colors-sprite {
background-image:url('/images-tmp/colors-s58671cb5bb.png');
background-repeat: no-repeat;
}
.blue {
text-indent:-119988px;
overflow:hidden;
text-align:left;
text-transform: capitalize;
background-position:0 0;
background-image:url('/images-tmp/colors-s58671cb5bb.png');
background-repeat:no-repeat;
}
.yellow {
text-indent:-119988px;
overflow:hidden;
text-align:left;
text-transform: capitalize;
background-position:0 -10px;
height:10px;
width:10px;
background-image:url('/images-tmp/colors-s58671cb5bb.png');
background-repeat:no-repeat;
}
CSS
assert_correct clean(other_css), clean(css)
end
it "should inline the sprite file" do
Compass.reset_configuration!
file = StringIO.new(<<-CONFIG)
images_path = #{@images_tmp_path.inspect}
generated_images_path = #{@generated_images_tmp_path.inspect}
CONFIG
Compass.add_configuration(file, "sprite_config")
Compass.configure_sass_plugin!
css = render <<-SCSS
$colors-inline:true;
@import "colors/*.png";
@include all-colors-sprites;
SCSS
other_css = <<-CSS
.colors-sprite, .colors-blue, .colors-yellow {
background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAUCAAAAACRhfOKAAAAHElEQVR42mM5wQADLP8JMRlIUIvE/IdgctLTNgCHDhEQVD4ceAAAAABJRU5ErkJggg==');
}
.colors-blue {
background-position:0 0;
}
.colors-yellow {
background-position:0 -10px;
}
CSS
assert_correct clean(other_css), clean(css)
end
it "should have a sprite_name function that returns the names of the sprites in a sass list" do
css = render <<-SCSS
@import "colors/*.png";
@each $color in sprite_names($colors-sprites) {
.\#{$color} {
width:0px;
}
}
SCSS
other_css = <<-CSS
.colors-sprite {
background-image: url('/images-tmp/colors-s58671cb5bb.png');
background-repeat: no-repeat;
}
.blue {
width:0px;
}
.yellow {
width:0px;
}
CSS
assert_correct clean(other_css), clean(css)
end
it "should respect global spacing" do
css = render <<-SCSS
$colors-spacing:5px;
@import "colors/*.png";
@include all-colors-sprites;
SCSS
other_css = <<-CSS
.colors-sprite, .colors-blue, .colors-yellow {
background-image: url('/images-tmp/colors-s747dec274e.png');
background-repeat: no-repeat;
}
.colors-blue {
background-position:0 0;
}
.colors-yellow {
background-position:0 -15px;
}
CSS
assert_correct clean(other_css), clean(css)
end
it "should return width and height of the map" do
css = render <<-SCSS
@import "colors/*.png";
.height { height : sprite_height($colors-sprites); }
.width { width : sprite_width($colors-sprites); }
SCSS
other_css = <<-CSS
.colors-sprite {
background-image: url('/images-tmp/colors-s58671cb5bb.png');
background-repeat: no-repeat;
}
.height {
height : 20px;
}
.width {
width : 10px;
}
CSS
assert_correct clean(other_css), clean(css)
end
it "should return width and height of a sprite" do
css = render <<-SCSS
@import "colors/*.png";
.height { height : sprite_height($colors-sprites, blue); }
.width { width : sprite_width($colors-sprites, blue); }
SCSS
other_css = <<-CSS
.colors-sprite {
background-image: url('/images-tmp/colors-s58671cb5bb.png');
background-repeat: no-repeat;
}
.height {
height : 10px;
}
.width {
width : 10px;
}
CSS
assert_correct clean(other_css), clean(css)
end
it "should render correct sprite with focus selector" do
css = render <<-SCSS
@import "focus/*.png";
@include all-focus-sprites;
SCSS
assert_correct <<-CSS, css
.focus-sprite, .focus-ten-by-ten {
background-image: url('/images-tmp/focus-sb5d1467be1.png');
background-repeat: no-repeat;
}
.focus-ten-by-ten {
background-position: 0 0;
}
.focus-ten-by-ten:hover, .focus-ten-by-ten.ten-by-ten-hover {
background-position: 0 -30px;
}
.focus-ten-by-ten:target, .focus-ten-by-ten.ten-by-ten-target {
background-position: 0 -40px;
}
.focus-ten-by-ten:active, .focus-ten-by-ten.ten-by-ten-active {
background-position: 0 -10px;
}
.focus-ten-by-ten:focus, .focus-ten-by-ten.ten-by-ten-focus {
background-position: 0 -20px;
}
CSS
end
end
================================================
FILE: cli/test/test_helper.rb
================================================
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
$:.unshift(lib_dir) unless $:.include?(lib_dir)
test_dir = File.dirname(__FILE__)
$:.unshift(test_dir) unless $:.include?(test_dir)
require 'compass'
require 'test/unit'
require 'true'
class String
def name
to_s
end
end
%w(command_line diff io rails test_case).each do |helper|
require "helpers/#{helper}"
end
class Test::Unit::TestCase
include Compass::Diff
include Compass::TestCaseHelper
include Compass::IoHelper
extend Compass::TestCaseHelper::ClassMethods
def fixture_path
File.join(File.expand_path('../', __FILE__), 'fixtures')
end
end
module SpriteHelper
URI = "selectors/*.png"
def init_sprite_helper
@images_proj_path = File.join(File.expand_path('../', __FILE__), 'fixtures', 'sprites', 'public')
@images_src_dir = 'images'
@images_src_path = File.join(@images_proj_path, @images_src_dir)
@images_tmp_dir = 'images-tmp'
@images_tmp_path = File.join(@images_proj_path, @images_tmp_dir)
end
def sprite_map_test(options, uri = URI)
importer = Compass::SpriteImporter.new
path, name = Compass::SpriteImporter.path_and_name(uri)
sprite_names = Compass::SpriteImporter.sprite_names(uri)
sass_engine = Compass::SpriteImporter.sass_engine(uri, name, importer, options)
map = Compass::SassExtensions::Sprites::SpriteMap.new(sprite_names.map{|n| uri.gsub('*', n)}, path, name, sass_engine, options)
map.options = {:compass => {:logger => Compass::NullLogger.new}}
map
end
def create_sprite_temp
init_sprite_helper
::FileUtils.cp_r @images_src_path, @images_tmp_path
end
def clean_up_sprites
init_sprite_helper
::FileUtils.rm_r @images_tmp_path
rescue Errno::ENOENT
#pass
end
end
================================================
FILE: cli/test/units/actions_test.rb
================================================
require 'test_helper'
require 'compass'
class ActionsTest < Test::Unit::TestCase
class BaseActionExtender
include Compass::Actions
def options
@@options ||= {}
end
def working_path
"/tmp"
end
end
# When log4r is included, it sometimes breaks the Actions
test "test_quiet_option" do
b = BaseActionExtender.new
b.logger = ""
b.options[:quiet] = true
# logger shouldn't be called... if it is, this will error
b.directory("/tmp/#{(rand * 1000000).to_i}")
end
end
================================================
FILE: cli/test/units/caniuse_test.rb
================================================
require 'test_helper'
require 'compass'
class CanIUseTest < Test::Unit::TestCase
def caniuse
Compass::Core::CanIUse.instance
end
DEFAULT_CAPABILITY_OPTIONS = [{:full_support => true}, {:partial_support => true}]
def test_unknown_browsers
assert_equal "unknown", Compass::Core::CanIUse::PUBLIC_BROWSER_NAMES["unknown"]
assert_equal "unknown", Compass::Core::CanIUse::CAN_I_USE_NAMES["unknown"]
end
def test_browser_names
assert_equal Compass::Core::CanIUse::PUBLIC_BROWSER_NAMES.values.sort, caniuse.browsers
end
def test_prefixes
assert_equal %w(-moz -ms -o -webkit), caniuse.prefixes
assert_equal %w(-moz -webkit), caniuse.prefixes(%w(chrome firefox safari))
end
def test_prefix
assert_equal "-webkit", caniuse.prefix("chrome")
assert_equal "-webkit", caniuse.prefix("safari")
assert_equal "-ms", caniuse.prefix("ie")
assert_equal "-webkit", caniuse.prefix("opera")
assert_equal "-o", caniuse.prefix("opera", "12.1")
end
def test_browsers_with_prefix
assert_equal %w(android android-chrome blackberry chrome ios-safari opera opera-mobile safari),
caniuse.browsers_with_prefix("-webkit").sort
assert_equal %w(android-firefox firefox),
caniuse.browsers_with_prefix("-moz").sort
end
def test_capabilities
# This is meant to break if a capability goes away or arrives
# So that we can think about what that means for compass
assert_equal [
"background-img-opts",
"border-image",
"border-radius",
"calc",
"css-animation",
"css-appearance",
"css-backgroundblendmode",
"css-boxshadow",
"css-canvas",
"css-counters",
"css-featurequeries",
"css-filters",
"css-fixed",
"css-gencontent",
"css-gradients",
"css-grid",
"css-hyphens",
"css-image-orientation",
"css-masks",
"css-mediaqueries",
"css-mixblendmode",
"css-opacity",
"css-placeholder",
"css-reflections",
"css-regions",
"css-repeating-gradients",
"css-resize",
"css-sel2",
"css-sel3",
"css-selection",
"css-shapes",
"css-sticky",
"css-table",
"css-textshadow",
"css-transitions",
"css-variables",
"css3-boxsizing",
"css3-colors",
"css3-cursors",
"css3-tabsize",
"flexbox",
"font-feature",
"fontface",
"getcomputedstyle",
"inline-block",
"intrinsic-width",
"kerning-pairs-ligatures",
"minmaxwh",
"multibackgrounds",
"multicolumn",
"object-fit",
"outline",
"pointer-events",
"rem",
"style-scoped",
"svg-css",
"text-decoration",
"text-overflow",
"text-size-adjust",
"text-stroke",
"transforms2d",
"transforms3d",
"ttf",
"user-select-none",
"viewport-units",
"word-break",
"wordwrap"],
caniuse.capabilities
end
def test_usage
total = 0
caniuse.browsers.each do |browser|
caniuse.versions(browser).each do |version|
usage = caniuse.usage(browser, version)
if usage.nil?
puts "nil usage for #{browser} at version #{version}"
next
end
total += usage
end
end
# all browsers add up to about 94%. that's... unfortunate.
assert total > 90 && total < 100
end
def test_prefixed_usage
assert 0 < caniuse.prefixed_usage("-webkit", "border-radius", DEFAULT_CAPABILITY_OPTIONS)
assert_equal 0, caniuse.prefixed_usage("-webkit", "outline", DEFAULT_CAPABILITY_OPTIONS)
assert_raises ArgumentError do
caniuse.prefixed_usage("-webkit", "unknown", DEFAULT_CAPABILITY_OPTIONS)
end
end
def test_requires_prefix
assert_raises ArgumentError do
caniuse.requires_prefix("chrome", "3", "border-radius", DEFAULT_CAPABILITY_OPTIONS)
end
assert_equal "-webkit", caniuse.requires_prefix("chrome", "4", "border-radius", DEFAULT_CAPABILITY_OPTIONS)
assert_equal nil, caniuse.requires_prefix("chrome", "5", "border-radius", DEFAULT_CAPABILITY_OPTIONS)
assert_equal nil, caniuse.requires_prefix("chrome", "30", "border-radius", DEFAULT_CAPABILITY_OPTIONS)
assert_equal "-webkit", caniuse.requires_prefix("opera", "16", "css-filters", DEFAULT_CAPABILITY_OPTIONS)
end
def test_browser_ranges_only_prefixed
mins = caniuse.browser_ranges("border-radius", "-webkit", false)
expected = {
"android"=>["2.1", "2.1"],
"chrome"=>["4", "4"],
"ios-safari"=>["3.2", "3.2"],
"safari"=>["3.1", "4"]
}
assert_equal(expected, mins)
end
def test_ranges_are_empty_when_prefix_doesnt_exit
mins = caniuse.browser_ranges("css-filters", "-o")
expected = {}
assert_equal(expected, mins)
end
def test_browser_ranges_including_unprefixed
mins = caniuse.browser_ranges("border-radius", "-webkit")
expected = {
"android"=>["2.1", "4.4.3"],
"chrome"=>["4", "39"],
"ios-safari"=>["3.2", "8"],
"safari"=>["3.1", "8"]
}
assert_equal(expected, mins)
end
def test_capability_matches
assert caniuse.capability_matches(
caniuse.browser_support("chrome", "10", "flexbox"),
[{:full_support => true}, {:partial_support => true, :spec_versions => [1]}])
assert !caniuse.capability_matches(
caniuse.browser_support("chrome", "10", "flexbox"),
[{:full_support => true}, {:partial_support => true, :spec_versions => [3]}])
end
def test_omitted_usage
assert_equal 0, caniuse.omitted_usage("chrome", "4")
assert_equal caniuse.usage("chrome", "4"), caniuse.omitted_usage("chrome", "5")
assert_equal caniuse.usage("chrome", "4"), caniuse.omitted_usage("chrome", "4", "4")
assert_equal caniuse.usage("chrome", "4") + caniuse.usage("chrome", "5"),
caniuse.omitted_usage("chrome", "4", "5")
end
end
================================================
FILE: cli/test/units/command_line_test.rb
================================================
require 'test_helper'
require 'fileutils'
require 'compass'
require 'compass/exec'
require 'timeout'
class CommandLineTest < Test::Unit::TestCase
include Compass::TestCaseHelper
include Compass::CommandLineHelper
include Compass::IoHelper
def teardown
Compass.reset_configuration!
end
def test_print_version
compass("-vq")
assert_match(/\d+\.\d+\.(\d+|((alpha|beta|rc)\.\d+\.[0-9a-f]+))?/, @last_result)
end
def test_basic_install
within_tmp_directory do
compass(*%w(create --boring basic))
assert File.exists?("basic/sass/screen.scss")
assert_action_performed :directory, "basic/"
assert_action_performed :create, "basic/sass/screen.scss"
end
end
Compass::Frameworks::ALL.each do |framework|
next if framework.name == "true"
next if framework.name == "testing"
next if framework.name =~ /^_/
define_method "test_#{framework.name}_installation" do
within_tmp_directory do
compass(*%W(create --boring --using #{framework.name} #{framework.name}_project))
assert File.exists?("#{framework.name}_project/sass/screen.scss"), "sass/screen.scss is missing. Found: #{Dir.glob("#{framework.name}_project/**/*").join(", ")}"
assert File.exists?("#{framework.name}_project/stylesheets/screen.css")
assert_action_performed :directory, "#{framework.name}_project/"
assert_action_performed :create, "#{framework.name}_project/sass/screen.scss"
assert_action_performed :write, "#{framework.name}_project/stylesheets/screen.css"
end
end
end
def test_basic_update
within_tmp_directory do
compass "create", "--boring", "basic"
Dir.chdir "basic" do
# basic update with timestamp caching
compass "compile", "--boring"
# assert_action_performed :unchanged, "sass/screen.scss"
# basic update with force option set
compass "compile", "--force", "--boring"
assert_action_performed :write, "stylesheets/screen.css"
end
end
end
end
================================================
FILE: cli/test/units/compass_util_test.rb
================================================
require 'test_helper'
class CompassUtilTest < Test::Unit::TestCase
def test_warn
$stderr, old_err = StringIO.new, $stderr
Compass::Util.compass_warn("this is a warning")
assert_match(/this is a warning/, $stderr.string)
ensure
$stderr = old_err
end
end
================================================
FILE: cli/test/units/compiler_test.rb
================================================
require 'test_helper'
require 'fileutils'
class CompilerTest < Test::Unit::TestCase
it "should strip css from file name and reappend" do
config = Compass::Configuration::Data.new("test",
:project_path => Dir.pwd,
:sass_dir => "foo",
:css_dir => "bar")
config.extend(Compass::Configuration::Defaults)
compiler = Compass.sass_compiler({}, config)
assert_equal 'screen', compiler.stylesheet_name(File.join(Dir.pwd, 'foo', 'screen.css.scss'))
end
end
================================================
FILE: cli/test/units/configuration_test.rb
================================================
require 'test_helper'
require 'compass'
require 'stringio'
class ConfigurationTest < Test::Unit::TestCase
setup do
Compass.reset_configuration!
@original_wd = Dir.pwd
FileUtils.rm_rf "test_tmp"
FileUtils.mkdir_p "test_tmp/images"
FileUtils.mkdir_p "test_tmp/fonts"
Dir.chdir "test_tmp"
end
after do
Compass.reset_configuration!
Dir.chdir @original_wd
FileUtils.rm_rf "test_tmp"
end
def test_parse_and_serialize
contents = StringIO.new(<<-CONFIG)
require 'compass'
require 'compass/import-once/activate'
# Require any additional compass plugins here.
project_type = :stand_alone
http_path = "/"
css_dir = "css"
sass_dir = "sass"
images_dir = "img"
javascripts_dir = "js"
output_style = :nested
# To enable relative paths to assets via compass helper functions. Uncomment:
# relative_assets = true
# To disable debugging comments that display the original location of your selectors. Uncomment:
# line_comments = false
# If you prefer the indented syntax, you might want to regenerate this
# project again passing --syntax sass, or you can uncomment this:
# preferred_syntax = :sass
# and then run:
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass
CONFIG
Compass.add_configuration(contents, "test_parse")
assert_equal 'sass', Compass.configuration.sass_dir
assert_equal 'css', Compass.configuration.css_dir
assert_equal 'img', Compass.configuration.images_dir
assert_equal 'js', Compass.configuration.javascripts_dir
expected_lines = contents.string.split("\n").map{|l|l.strip}
actual_lines = Compass.configuration.serialize.split("\n").map{|l|l.strip}
assert_correct expected_lines, actual_lines
end
def test_custom_watch
contents = StringIO.new(<<-CONFIG)
watch 'img/**/*' do
puts 'foobar'
end
CONFIG
Compass.add_configuration(contents, 'test_watch_config')
watch = Compass.configuration.watches.first
assert_equal 'img/**/*', watch.glob
assert watch.is_a?(Compass::Configuration::Watch)
end
def test_serialization_warns_with_asset_host_set
contents = StringIO.new(<<-CONFIG)
asset_host do |path|
"http://example.com"
end
CONFIG
Compass.add_configuration(contents, "test_serialization_warns_with_asset_host_set")
warning = capture_warning do
Compass.configuration.serialize
end
assert_equal "WARNING: asset_host is code and cannot be written to a file. You'll need to copy it yourself.\n", warning
end
class TestData < Compass::Configuration::FileData
def initialize
super(:test)
end
inherited_array :stuff, :clobbers => true
inherited_array :accumulated
end
def test_accumulated_array_does_not_clobber
data1 = TestData.new
data1.accumulated = [:a]
data2 = TestData.new
data2.accumulated = [:b]
data2.inherit_from!(data1)
assert_equal [:b, :a], data2.accumulated.to_a
end
def test_inherited_array_can_clobber
data1 = TestData.new
data1.stuff = [:a]
data2 = TestData.new
data2.stuff = [:b]
data2.inherit_from!(data1)
assert_equal [:b], data2.stuff.to_a
end
def test_inherited_array_can_append
data1 = TestData.new
data1.stuff = [:a]
data2 = TestData.new
data2.stuff << :b
data2.inherit_from!(data1)
assert_equal [:b, :a], data2.stuff.to_a
end
def test_inherited_array_can_append_2
data1 = TestData.new
data1.stuff = [:a]
data2 = TestData.new
data2.stuff << :b
data2.inherit_from!(data1)
data3 = TestData.new
data3.stuff << :c
data3.inherit_from!(data2)
assert_equal [:c, :b, :a], data3.stuff.to_a
end
def test_inherited_array_can_remove
data1 = TestData.new
data1.stuff = [:a]
data2 = TestData.new
data2.stuff >> :a
data2.inherit_from!(data1)
assert_equal [], data2.stuff.to_a
end
def test_inherited_array_combined_augmentations
data1 = TestData.new
data1.stuff = [:a]
data2 = TestData.new
data2.stuff >> :a
data2.stuff << :b
data2.inherit_from!(data1)
assert_equal [:b], data2.stuff.to_a
end
def test_inherited_array_long_methods
data1 = TestData.new
data1.stuff = [:a]
data2 = TestData.new
data2.remove_from_stuff(:a)
data2.add_to_stuff(:b)
data2.inherit_from!(data1)
assert_equal [:b], data2.stuff.to_a
end
def test_inherited_array_augmentations_can_be_clobbered
data1 = TestData.new
data1.stuff = [:a]
data2 = TestData.new
data2.stuff >> :a
data2.stuff << :b
data2.stuff = [:c]
data2.inherit_from!(data1)
assert_equal [:c], data2.stuff.to_a
end
def test_inherited_array_augmentations_after_clobbering
data1 = TestData.new
data1.stuff = [:a]
data2 = TestData.new
data2.stuff >> :a
data2.stuff << :b
data2.stuff = [:c, :d]
data2.stuff << :e
data2.stuff >> :c
data2.inherit_from!(data1)
assert_equal [:d, :e], data2.stuff.to_a
end
def test_serialization_warns_with_asset_cache_buster_set
contents = StringIO.new(<<-CONFIG)
asset_cache_buster do |path|
"http://example.com"
end
CONFIG
Compass.add_configuration(contents, "test_serialization_warns_with_asset_cache_buster_set")
assert_kind_of Proc, Compass.configuration.asset_cache_buster_without_default
assert_equal "http://example.com", Compass.configuration.asset_cache_buster_without_default.call("whatever")
warning = capture_warning do
Compass.configuration.serialize
end
assert_equal "WARNING: asset_cache_buster is code and cannot be written to a file. You'll need to copy it yourself.\n", warning
end
def test_cache_buster_file_not_passed_when_the_file_does_not_exist
config = Compass::Configuration::Data.new("test_cache_buster_file_not_passed_when_the_file_does_not_exist")
the_file = nil
was_called = nil
config.asset_cache_buster do |path, file|
was_called = true
the_file = file
"busted=true"
end
Compass.add_configuration(config)
sass = Sass::Engine.new(<<-SCSS, Compass.configuration.to_sass_engine_options.merge(:syntax => :scss))
.foo { background: image-url("asdf.gif") }
SCSS
sass.render
assert was_called
assert_nil the_file
end
def test_cache_buster_file_is_closed
config = Compass::Configuration::Data.new("test_cache_buster_file_is_closed")
the_file = nil
was_called = nil
FileUtils.touch "images/asdf.gif"
config.asset_cache_buster do |path, file|
was_called = true
the_file = file
"busted=true"
end
Compass.add_configuration(config)
sass = Sass::Engine.new(<<-SCSS, Compass.configuration.to_sass_engine_options.merge(:syntax => :scss))
.foo { background: image-url("asdf.gif") }
SCSS
sass.render
assert was_called
assert_kind_of File, the_file
assert the_file.closed?
end
def test_cache_buster_handles_id_refs_for_images
config = Compass::Configuration::Data.new("test_cache_buster_file_is_closed")
the_file = nil
was_called = nil
FileUtils.touch "images/asdf.svg"
config.asset_cache_buster do |path, file|
was_called = true
the_file = file
"busted=true"
end
Compass.add_configuration(config)
sass = Sass::Engine.new(<<-SCSS, Compass.configuration.to_sass_engine_options.merge(:syntax => :scss))
.foo { background: image-url("asdf.svg#image-1") }
SCSS
result = sass.render
assert was_called
assert_kind_of File, the_file
assert the_file.closed?
assert_equal < :scss))
.foo { background: image-url("asdf.svg#image-1") }
SCSS
result = sass.render
assert_equal < :scss))
.foo { background: font-url("asdf.ttf#iefix") }
SCSS
result = sass.render
assert was_called
assert_kind_of File, the_file
assert the_file.closed?
assert_equal <> :c
assert_equal <> :c
CONFIG
end
def test_inherited_arrays_clobbering_with_augmentations_serialize
inherited = TestData.new
inherited.stuff << :a
d = TestData.new
d.stuff << :b
d.stuff = [:c, :d]
d.stuff << :e
assert_equal < 'bar'}
CONFIG
Compass.add_configuration(contents, "test_sass_options")
assert_equal 'bar', Compass.configuration.to_sass_engine_options[:foo]
assert_equal 'bar', Compass.configuration.to_sass_plugin_options[:foo]
expected_serialization = <\"bar\"}
# To disable debugging comments that display the original location of your selectors. Uncomment:
# line_comments = false
# If you prefer the indented syntax, you might want to regenerate this
# project again passing --syntax sass, or you can uncomment this:
# preferred_syntax = :sass
# and then run:
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass
EXPECTED
assert_correct(expected_serialization, Compass.configuration.serialize)
end
def test_sprite_load_path_clobbers
contents = StringIO.new(<<-CONFIG)
sprite_load_path = ["/Users/chris/Projects/my_compass_project/images/sprites"]
CONFIG
Compass.add_configuration(contents, "test_sass_options")
assert_equal ["/Users/chris/Projects/my_compass_project/images/sprites"], Compass.configuration.sprite_load_path.to_a
expected_serialization = < :scss).render # raises an error if we generated invalid css
end
end
end
end
================================================
FILE: cli/test/units/sass_extensions_test.rb
================================================
require 'test_helper'
class SassExtensionsTest < Test::Unit::TestCase
def test_simple
assert_equal "a b", evaluate(%Q{nest("a", "b")})
end
def test_left_side_expansion
assert_equal "a c, b c", evaluate(%Q{nest("a, b", "c")})
end
def test_right_side_expansion
assert_equal "a b, a c", evaluate(%Q{nest("a", "b, c")})
end
def test_both_sides_expansion
assert_equal "a c, a d, b c, b d", evaluate(%Q{nest("a, b", "c, d")})
end
def test_three_selectors_expansion
assert_equal "a b, a c, a d", evaluate(%Q{nest("a", "b, c, d")})
end
def test_third_argument_expansion
assert_equal "a b e, a b f, a c e, a c f, a d e, a d f", evaluate(%Q{nest("a", "b, c, d", "e, f")})
end
def test_enumerate
assert_equal ".grid-1, .grid-2, .grid-3", evaluate(%Q{enumerate(".grid", 1, 3, "-")})
end
def test_append_selector
assert_equal "div.bar", evaluate(%Q{append_selector("div", ".bar")})
assert_equal ".foo1.bar1, .foo1.bar2, .foo2.bar1, .foo2.bar2", evaluate(%Q{append_selector(".foo1, .foo2", ".bar1, .bar2")})
end
def test_headers
assert_equal "h1, h2, h3, h4, h5, h6", evaluate("headers()")
assert_equal "h1, h2, h3, h4, h5, h6", evaluate("headers(all)")
assert_equal "h1, h2, h3, h4", evaluate("headers(4)")
assert_equal "h2, h3", evaluate("headers(2,3)")
assert_equal "h4, h5, h6", evaluate("headers(4,6)")
end
def test_scale_lightness
assert_equal "75%", evaluate("lightness(scale-lightness(hsl(50deg, 50%, 50%), 50%))")
assert_equal "25%", evaluate("lightness(scale-lightness(hsl(50deg, 50%, 50%), -50%))")
end
def test_adjust_lightness
assert_equal "75%", evaluate("lightness(adjust-lightness(hsl(50deg, 50%, 50%), 25%))")
assert_equal "25%", evaluate("lightness(adjust-lightness(hsl(50deg, 50%, 50%), -25%))")
assert_equal "100%", evaluate("lightness(adjust-lightness(hsl(50deg, 50%, 50%), 500%))")
assert_equal "0%", evaluate("lightness(adjust-lightness(hsl(50deg, 50%, 50%), -500%))")
end
def test_scale_saturation
assert_equal "75%", evaluate("saturation(scale-saturation(hsl(50deg, 50%, 50%), 50%))")
assert_equal "25%", evaluate("saturation(scale-saturation(hsl(50deg, 50%, 50%), -50%))")
end
def test_adjust_saturation
assert_equal "75%", evaluate("saturation(adjust-saturation(hsl(50deg, 50%, 50%), 25%))")
assert_equal "25%", evaluate("saturation(adjust-saturation(hsl(50deg, 50%, 50%), -25%))")
end
def test_shade
assert_equal evaluate("mix(black, #ff0, 25%)"), evaluate("shade(#ff0, 25%)")
assert_equal evaluate("mix(black, #ff0, 0%)"), evaluate("shade(#ff0, 0%)")
end
def test_tint
assert_equal evaluate("mix(white, #ff0, 75%)"), evaluate("tint(#ff0, 75%)")
assert_equal evaluate("mix(white, #ff0, 100%)"), evaluate("tint(#ff0, 100%)")
end
def test_if_function
assert_equal "no", evaluate("if(false, yes, no)")
assert_equal "yes", evaluate("if(true, yes, no)")
end
def test_math_functions
assert_equal "0.84147", evaluate("sin(1)")
assert_equal "0.84147px", evaluate("sin(1px)")
assert_equal "0.5236", evaluate("asin(0.5)")
assert_equal "0.5236", evaluate("asin(100px/200px)")
assert_equal "0.0", evaluate("sin(pi())")
assert_equal "1", evaluate("sin(pi() / 2)")
assert_equal "0.0", evaluate("sin(180deg)")
assert_equal "-1", evaluate("sin(3* pi() / 2)")
assert_equal "-1", evaluate("cos(pi())")
assert_equal "1", evaluate("cos(360deg)")
assert_equal "1.0472", evaluate("acos(0.5)")
assert_equal "1.0472", evaluate("acos(100px/200px)")
assert_equal "-0.17605", evaluate("sin(270)")
assert_equal "1", evaluate("cos(2*pi())")
assert_equal "0.0", evaluate("cos(pi() / 2)")
assert_equal "0.0", evaluate("cos(3* pi() / 2)")
assert_equal "0.0", evaluate("tan(pi())")
assert_equal "0.46365", evaluate("atan(0.5)")
assert_equal "0.0", evaluate("tan(360deg)")
assert_equal "0.95892", evaluate("sin(360)")
assert evaluate("tan(pi()/2 - 0.0001)").to_f > 1000, evaluate("tan(pi()/2 - 0.0001)")
assert evaluate("tan(pi()/2 + 0.0001)").to_f < -1000, evaluate("tan(pi()/2 - 0.0001)")
assert_equal "0.69315px", evaluate("logarithm(2px)")
assert_equal "0", evaluate("logarithm(1)")
assert_equal "1", evaluate("logarithm(e())")
assert_equal "1", evaluate("logarithm($number: e())")
assert_equal "1", evaluate("logarithm(10, $base: 10)")
assert_equal "5px", evaluate("sqrt(25px)")
assert_equal "5px", evaluate("sqrt($number: 25px)")
assert_equal "5px", evaluate("square-root(25px)")
assert_equal "5px", evaluate("square-root($number: 25px)")
assert_equal "25px", evaluate("pow(5px, 2)")
assert_equal "25px", evaluate("pow($number: 5px, $exponent: 2)")
assert_equal "79.43236px", evaluate("pow(5px, e())")
assert((0..2).include?(evaluate("random(2)").to_i))
random_warning = capture_warning do
assert((4..16).include?(evaluate("random(4, 16)").to_i))
end
assert_equal < e
raise e unless e.message =~ /isn't a valid CSS value/
result.inspect
end
end
end
================================================
FILE: cli/test/units/sass_extenstions/gradients_test.rb
================================================
class GradientTestClass
extend Compass::Core::SassExtensions::Functions::Constants
extend Compass::Core::SassExtensions::Functions::GradientSupport::Functions
def self.options
{}
end
end
require 'test_helper'
require 'compass'
class GradientsTest < Test::Unit::TestCase
include Sass::Script::Value::Helpers
def klass
GradientTestClass
end
test "should return correct angle" do
assert_equal number(330, 'deg'), klass.convert_angle_from_offical(number(120, 'deg'))
end
test "Should convert old to new" do
[:top => ['to', 'bottom'], :bottom => ['to', 'top'], :left => ['to', 'right'], :right => ['to', 'left']].each do |test_value|
assert_equal list(identifier(test_value.keys.first.to_s), :space), klass.convert_angle_from_offical(
list(identifier(test_value.values[0].first), identifier(test_value.values[0].last), :space))
end
end
end
================================================
FILE: cli/test/units/sprites/engine_test.rb
================================================
require 'test_helper'
class EngineTest < Test::Unit::TestCase
include SpriteHelper
def setup
create_sprite_temp
sprite_filename = 'squares/ten-by-ten.png'
@images = [
Compass::SassExtensions::Sprites::Image.new(nil, File.join(sprite_filename), {})
]
@engine = Compass::SassExtensions::Sprites::Engine.new(100, 100, @images)
end
def taredown
clean_up_sprites
end
test "should have width of 100" do
assert_equal 100, @engine.width
end
test "should have height of 100" do
assert_equal 100, @engine.height
end
test "should have correct images" do
assert_equal @images, @engine.images
end
test "raises Compass::Error when calling save" do
begin
@engine.save('foo')
assert false, '#save did not raise an exception'
rescue Compass::Error
assert true
end
end
test "raises Compass::Error when calling construct_sprite" do
begin
@engine.construct_sprite
assert false, '#construct_sprite did not raise an exception'
rescue Compass::Error
assert true
end
end
end
================================================
FILE: cli/test/units/sprites/image_row_test.rb
================================================
require 'test_helper'
class ImageRowTest < Test::Unit::TestCase
include SpriteHelper
def setup
clean_up_sprites
create_sprite_temp
file = StringIO.new("images_path = #{@images_src_path.inspect}\n")
Compass.add_configuration(file, "sprite_config")
@filenames = %w(large.png large_square.png medium.png tall.png small.png)
@image_files = Dir["#{@images_src_path}/image_row/*.png"].sort
@images = @image_files.map do |img|
img.gsub!("#{@images_src_path}/", '')
Compass::SassExtensions::Sprites::Image.new(nil, img, {})
end
image_row(1000)
end
def teardown
clean_up_sprites
end
def image_row(max)
@image_row = Compass::SassExtensions::Sprites::ImageRow.new(max)
end
def populate_row
@images.each do |image|
assert @image_row.add(image)
end
end
it "should return false if image will not fit in row" do
image_row(100)
img = Compass::SassExtensions::Sprites::Image.new(nil, File.join('image_row', 'large.png'), {})
assert !@image_row.add(img)
end
it "should have 5 images" do
populate_row
assert_equal 5, @image_row.images.size
end
it "should return max image width" do
populate_row
assert_equal 400, @image_row.width
end
it "should return max image height" do
populate_row
assert_equal 40, @image_row.height
end
it "should have an efficiency rating" do
populate_row
assert_equal 1 - (580.0 / 1000.0), @image_row.efficiency
end
end
================================================
FILE: cli/test/units/sprites/image_test.rb
================================================
require 'test_helper'
require 'mocha'
require 'ostruct'
class SpritesImageTest < Test::Unit::TestCase
include SpriteHelper
def setup
create_sprite_temp
end
def teardown
clean_up_sprites
end
SPRITE_FILENAME = 'selectors/ten-by-ten.png'
def sprite_path
File.join(@images_tmp_path, SPRITE_FILENAME)
end
def sprite_name
File.basename(SPRITE_FILENAME, '.png')
end
def digest
Digest::MD5.file(sprite_path).hexdigest
end
def test_map(options ={})
options = {'cleanup' => Sass::Script::Bool.new(true), 'layout' => Sass::Script::String.new('vertical')}.merge(options)
map = sprite_map_test(options)
end
def test_image(options ={})
test_map(options).images.first
end
test 'initialize' do
image = test_image
assert_equal sprite_name, image.name
assert_equal sprite_path, image.file
assert_equal SPRITE_FILENAME, image.relative_file
assert_equal 10, image.width
assert_equal 10, image.height
assert_equal digest, image.digest
assert_equal 0, image.top
assert_equal 0, image.left
end
test 'hover' do
assert_equal 'ten-by-ten_hover', test_image.hover.name
end
test 'hover should find image by _ or - in file name' do
map = test_map(:seperator => '-')
map.images.each_index do |i|
if map.images[i].name == 'ten-by-ten_hover'
map.images[i].stubs(:name).returns('ten-by-ten-hover')
end
end
test_image = map.images.first
assert_equal 'ten-by-ten-hover', test_image.hover.name
end
test 'no parent' do
assert_nil test_image.parent
end
test 'image type is "global" should raise exception' do
assert_raise ::Compass::SpriteException do
image = test_image "selectors_ten_by_ten_repeat" => Sass::Script::String.new('global')
image.repeat
end
end
test 'image type is "no-repeat"' do
img = test_image
assert_equal 'no-repeat', img.repeat
assert img.no_repeat?
end
test 'image repeat-x' do
img = test_image "selectors_ten_by_ten_repeat" => Sass::Script::String.new('repeat-x')
assert img.repeat_x?
end
test 'image repeat-y' do
img = test_image "selectors_ten_by_ten_repeat" => Sass::Script::String.new('repeat-y')
assert img.repeat_y?
end
test 'image position' do
image = test_image "selectors_ten_by_ten_position" => Sass::Script::Number.new(100, ["px"])
assert_equal 100, image.position.value
end
test 'image spacing' do
@spacing = 10
image = test_image "spacing" => Sass::Script::Number.new(100, ["px"])
assert_equal 100, image.spacing
end
test 'offset' do
image = test_image "selectors_ten_by_ten_position" => Sass::Script::Number.new(100, ["px"])
assert_equal 100, image.offset
end
test 'neither, uses 0' do
img = test_image
img.position.stubs(:unitless?).returns(false)
assert_equal 0, img.offset
end
end
================================================
FILE: cli/test/units/sprites/images_test.rb
================================================
require 'test_helper'
require 'compass/sass_extensions/sprites/images'
class ImagesTest < Test::Unit::TestCase
def setup
@images = Compass::SassExtensions::Sprites::Images.new
@images << OpenStruct.new(:foo => 1, :name => 'bob', :size => 1200, :width => 10)
@images << OpenStruct.new(:foo => 2, :name => 'bob', :size => 300, :width => 100)
@images << OpenStruct.new(:foo => 3, :name => 'aob', :size => 120, :width => 50)
@images << OpenStruct.new(:foo => 4, :name => 'zbob', :size => 600, :width => 55)
end
test "sort by size" do
@images.sort_by! :size
assert_equal [3, 2, 4, 1], @images.map(&:foo)
end
test "sort by !size" do
@images.sort_by! '!size'
assert_equal [3, 2, 4, 1].reverse, @images.map(&:foo)
end
test "sort by name" do
@images.sort_by! :name
assert_equal [3, 2, 1, 4], @images.map(&:foo)
end
test "sort by !name" do
@images.sort_by! '!name'
assert_equal [3, 2, 1, 4].reverse, @images.map(&:foo)
end
test "sort by width" do
@images.sort_by! :width
assert_equal [1, 3, 4, 2], @images.map(&:foo)
end
test "sort by !width" do
@images.sort_by! '!width'
assert_equal [1, 3, 4, 2].reverse, @images.map(&:foo)
end
end
================================================
FILE: cli/test/units/sprites/importer_test.rb
================================================
require 'test_helper'
class ImporterTest < Test::Unit::TestCase
include SpriteHelper
def setup
create_sprite_temp
file = StringIO.new("images_path = #{@images_src_path.inspect}\n")
Compass.add_configuration(file, "sprite_config")
@importer = Compass::SpriteImporter.new
end
def teardown
Compass.reset_configuration!
end
def options
{:foo => 'bar'}
end
test "should use search path to find sprites" do
Compass.reset_configuration!
uri = 'foo/*.png'
other_folder = File.join(@images_tmp_path, '../other-temp')
FileUtils.mkdir_p other_folder
FileUtils.mkdir_p File.join(other_folder, 'foo')
%w(my bar).each do |file|
FileUtils.touch(File.join(other_folder, "foo/#{file}.png"))
end
config = Compass::Configuration::Data.new('config')
config.images_path = @images_tmp_path
config.sprite_load_path = [@images_tmp_path, other_folder]
Compass.add_configuration(config, "sprite_config")
importer = Compass::SpriteImporter.new
assert_equal 2, Compass.configuration.sprite_load_path.compact.size
assert Compass.configuration.sprite_load_path.include?(other_folder)
assert_equal ["bar", "my"], Compass::SpriteImporter.sprite_names(uri)
FileUtils.rm_rf other_folder
end
test "name should return the sprite name" do
assert_equal 'selectors', Compass::SpriteImporter.sprite_name(URI)
end
test "path should return the sprite path" do
assert_equal 'selectors', Compass::SpriteImporter.path(URI)
end
test "should return all the sprite names" do
assert_equal ["ten-by-ten", "ten-by-ten_active", "ten-by-ten_hover", "ten-by-ten_target"], Compass::SpriteImporter.sprite_names(URI)
end
test "should have correct mtime" do
thirtydays = Time.now.to_i + (60*60*24*30)
file = Dir[File.join(@images_src_path, URI)].sort.first
File.utime(thirtydays, thirtydays, file)
assert_equal thirtydays, File.mtime(file).to_i
assert_equal thirtydays, @importer.mtime(URI, {}).to_i
end
test "should return sass engine on find" do
assert @importer.find(URI, {}).is_a?(Sass::Engine)
end
test "sass options should contain options" do
opts = Compass::SpriteImporter.sass_options('foo', @importer, options)
assert_equal 'bar', opts[:foo]
end
test "verify that the sass_engine passes the correct filename" do
importer = Compass::SpriteImporter.new
engine = Compass::SpriteImporter.sass_engine(URI, 'foo', importer, options)
assert_equal engine.options[:filename], URI
end
test "should fail given bad sprite extensions" do
@images_src_path = File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'sprites', 'public', 'images')
file = StringIO.new("images_path = #{@images_src_path.inspect}\n")
Compass.add_configuration(file, "sprite_config")
importer = Compass::SpriteImporter.new
uri = "bad_extensions/*.jpg"
begin
Compass::SpriteImporter.sass_engine(uri, Compass::SpriteImporter.sprite_name(uri), importer, {})
assert false, "An invalid sprite file made it past validation."
rescue Compass::Error => e
assert e.message.include?("invalid sprite path")
end
end
end
================================================
FILE: cli/test/units/sprites/layout_test.rb
================================================
require 'test_helper'
class LayoutTest < Test::Unit::TestCase
include SpriteHelper
def setup
Hash.send(:include, Compass::SassExtensions::Functions::Sprites::VariableReader)
clean_up_sprites
create_sprite_temp
file = StringIO.new("images_path = #{@images_tmp_path.inspect}\n")
Compass.add_configuration(file, "sprite_config")
Compass.configure_sass_plugin!
@options = {'cleanup' => Sass::Script::Bool.new(true), 'layout' => Sass::Script::String.new('vertical')}
end
def teardown
clean_up_sprites
end
# HELPERS
def vertical
opts = @options.merge("layout" => Sass::Script::String.new('vertical'))
sprite_map_test(opts)
end
def smart
options = @options.merge("layout" => Sass::Script::String.new('smart'))
importer = Compass::SpriteImporter.new
uri = "image_row/*.png"
path, name = Compass::SpriteImporter.path_and_name(uri)
sprite_names = Compass::SpriteImporter.sprite_names(uri)
sass_engine = Compass::SpriteImporter.sass_engine(uri, name, importer, options)
map = Compass::SassExtensions::Sprites::SpriteMap.new(sprite_names.map {|n| "image_row/#{n}.png"}, path, name, sass_engine, options)
map.options = {:compass => {:logger => Compass::NullLogger.new}}
map
end
def diagonal
opts = @options.merge("layout" => Sass::Script::String.new('diagonal'))
sprite_map_test(opts)
end
def horizontal(options= {}, uri=URI)
opts = @options.merge("layout" => Sass::Script::String.new('horizontal'))
opts.merge!(options)
sprite_map_test(opts, uri)
end
# REPEAT_X
test 'repeat-x layout single image' do
opts = {"repeat_x_three_repeat" => Sass::Script::String.new('repeat-x'), 'sort_by' => Sass::Script::String.new('width')}
map = sprite_map_test(@options.merge(opts), 'repeat_x/*.png')
assert_equal 6, map.width
assert_equal [0, 1, 3, 6, 10, 3, 3], map.images.map(&:top)
assert_equal [0, 0, 0, 0, 0, 0, 3], map.images.map(&:left)
end
test 'repeat-x layout multi image' do
opts = {"repeat_x_three_repeat" => Sass::Script::String.new('repeat-x'), "repeat_x_four_repeat" => Sass::Script::String.new('repeat-x')}
map = sprite_map_test(@options.merge(opts), 'repeat_x/*.png')
assert_equal 12, map.width
end
test "repeat-y layout single image" do
opts = {"layout" => Sass::Script::String.new('horizontal'), "squares_ten_by_ten_repeat" => Sass::Script::String.new('repeat-y')}
map = sprite_map_test(@options.merge(opts), 'squares/*.png')
assert_equal 30, map.width
assert_equal 20, map.height
assert_equal 3, map.images.size
assert_equal [[0,0], [0,10], [10,0]], map.images.map { |img| [img.top, img.left] }
assert map.horizontal?
end
test "repeat-y layout multi image" do
opts = {"layout" => Sass::Script::String.new('horizontal'), "repeat_x_three_repeat" => Sass::Script::String.new('repeat-y'), "repeat_x_four_repeat" => Sass::Script::String.new('repeat-y')}
map = sprite_map_test(@options.merge(opts), 'repeat_x/*.png')
assert_equal [[0, 0], [0, 5], [0, 9], [0, 10], [0, 13], [4, 5], [8, 5], [3, 10], [6, 10], [9, 10]], map.images.map { |img| [img.top, img.left] }
end
# VERTICAL LAYOUT
it "should have a vertical layout" do
vert = vertical
assert_equal [0, 10, 20, 30], vert.images.map(&:top)
assert_equal [0, 0, 0, 0], vert.images.map(&:left)
assert vert.vertical?
end
it "should have a vertical layout with spacing" do
vert = sprite_map_test(@options.merge({"spacing" => Sass::Script::Number.new(10, ['px'])}))
assert_equal [0, 20, 40, 60], vert.images.map(&:top)
end
it "should layout vertical with position" do
vert = sprite_map_test("selectors_ten_by_ten_active_position" => Sass::Script::Number.new(10, ['px']))
assert_equal [0, 10, 0, 0], vert.images.map(&:left)
end
it "should generate vertical sprites in decending order" do
sizes = vertical.images.map{|image| File.size(image.file) }
assert_equal sizes.min, File.size(vertical.images.first.file)
assert_equal sizes.max, File.size(vertical.images.last.file)
end
# SMART LAYOUT
it "should have a smart layout" do
base = smart
base.generate
assert base.smart?
assert_equal 400, base.width
assert_equal 60, base.height
assert_equal [[0, 0], [20, 120], [20, 0], [20, 100], [20, 160]], base.images.map {|i| [i.top, i.left]}
assert File.exists?(base.filename)
FileUtils.rm base.filename
end
# DIAGONAL LAYOUT
it "should generate a diagonal sprite" do
base = diagonal
base.generate
assert base.diagonal?
assert_equal 40, base.width
assert_equal 40, base.height
assert_equal [[30, 0], [20, 10], [10, 20], [0, 30]], base.images.map {|i| [i.top, i.left]}
assert File.exists?(base.filename)
FileUtils.rm base.filename
end
# HORIZONTAL LAYOUT
it "should have a horizontal layout" do
base = horizontal
assert base.horizontal?
assert_equal 10, base.height
assert_equal 40, base.width
end
it "should layout images horizontaly" do
base = horizontal
assert_equal [0, 10, 20, 30], base.images.map(&:left)
assert_equal [0, 0, 0, 0], base.images.map(&:top)
end
it "should layout horizontaly with spacing" do
base = horizontal("spacing" => Sass::Script::Number.new(10, ['px']))
assert_equal [0, 20, 40, 60], base.images.map(&:left)
assert_equal [0, 0, 0, 0], base.images.map(&:top)
assert_equal 80, base.width
end
it "should layout horizontaly with spacing and and position" do
base = horizontal({"spacing" => Sass::Script::Number.new(10, ['px']), "position" => Sass::Script::Number.new(50, ['%'])}, 'squares/*.png')
assert_equal [0, 20], base.images.map(&:left)
assert_equal [5, 0], base.images.map(&:top)
assert_equal 50, base.width
end
it "should layout horizontaly with position" do
base = horizontal("selectors_ten_by_ten_active_position" => Sass::Script::Number.new(10, ['px']))
assert_equal [0, 10, 0, 0], base.images.map(&:top)
assert_equal 40, base.width
assert_equal 20, base.height
end
it "should generate a horrizontal sprite" do
base = horizontal
base.generate
assert File.exists?(base.filename)
FileUtils.rm base.filename
end
end
================================================
FILE: cli/test/units/sprites/row_fitter_test.rb
================================================
require 'test_helper'
require 'compass/sass_extensions/sprites/row_fitter'
class RowFitterTest < Test::Unit::TestCase
include SpriteHelper
def setup
file = StringIO.new("images_path = #{@images_src_path.inspect}\n")
Compass.add_configuration(file, "sprite_config")
end
def row_fitter(images = nil)
@row_fitter ||= Compass::SassExtensions::Sprites::RowFitter.new(images)
end
def teardown
@row_fitter = nil
end
def create_images(dims)
dims.collect { |width, height|
image = Compass::SassExtensions::Sprites::Image.new('blah', 'blah', {})
image.stubs(:width => width, :height => height)
image
}
end
def basic_dims
[
[ 100, 10 ],
[ 80, 10 ],
[ 50, 10 ],
[ 35, 10 ],
[ 20, 10 ]
]
end
it 'should use the fast placement algorithm' do
images = create_images(basic_dims)
row_fitter(images)
assert_equal 100, row_fitter.width
row_fitter.fit!(:fast)
assert_equal 4, row_fitter.rows.length
assert_equal [ images[0] ], row_fitter[0].images
assert_equal [ images[1] ], row_fitter[1].images
assert_equal [ images[2], images[3] ], row_fitter[2].images
assert_equal [ images[4] ], row_fitter[3].images
end
it 'should use the scan placement algorithm' do
images = create_images(basic_dims)
row_fitter(images)
row_fitter.fit!(:scan)
assert_equal 3, row_fitter.rows.length
assert_equal [ images[0] ], row_fitter[0].images
assert_equal [ images[1], images[4] ], row_fitter[1].images
assert_equal [ images[2], images[3] ], row_fitter[2].images
end
end
================================================
FILE: cli/test/units/sprites/sprite_command_test.rb
================================================
require 'test_helper'
require 'compass/exec'
class SpriteCommandTest < Test::Unit::TestCase
include Compass::TestCaseHelper
include Compass::CommandLineHelper
include Compass::IoHelper
attr_reader :test_dir
include SpriteHelper
def setup
@before_dir = ::Dir.pwd
create_temp_cli_dir
create_sprite_temp
@config_file = File.join(@test_dir, 'config.rb')
File.open(@config_file, 'w') do |f|
f << config_data
end
end
def config_data
return <<-CONFIG
images_path = "#{@images_tmp_path}"
CONFIG
end
def create_temp_cli_dir
directory = File.join(File.expand_path('../', __FILE__), 'test')
::FileUtils.mkdir_p directory
@test_dir = directory
end
def run_compass_with_options(options)
output = 'foo'
::Dir.chdir @test_dir
compass *options
end
def options_to_cli(options)
options.map.flatten!
end
def teardown
::Dir.chdir @before_dir
clean_up_sprites
if File.exists?(@test_dir)
::FileUtils.rm_r @test_dir
end
end
it "should create sprite file" do
assert_equal 0, run_compass_with_options(['sprite', "-f", 'stylesheet.scss', "squares/*.png"]).to_i
assert File.exists?(File.join(test_dir, 'stylesheet.scss'))
end
end
================================================
FILE: cli/test/units/sprites/sprite_map_test.rb
================================================
require 'test_helper'
class SpriteMapTest < Test::Unit::TestCase
include SpriteHelper
def setup
Hash.send(:include, Compass::SassExtensions::Functions::Sprites::VariableReader)
create_sprite_temp
file = StringIO.new(<<-CONFIG)
project_path = "#{@images_proj_path}"
images_dir = "#{@images_tmp_dir}"
CONFIG
Compass.add_configuration(file, "sprite_config")
Compass.configure_sass_plugin!
@options = {'cleanup' => Sass::Script::Bool.new(true), 'layout' => Sass::Script::String.new('vertical')}
@base = sprite_map_test(@options)
end
def teardown
clean_up_sprites
@base = nil
end
it "should have the correct size" do
assert_equal [10,40], @base.size
end
it "should have the sprite names" do
assert_equal Compass::SpriteImporter.sprite_names(URI), @base.sprite_names
end
it 'should have image filenames' do
assert_equal Dir["#{@images_tmp_path}/selectors/*.png"].sort, @base.image_filenames
end
it 'should need generation' do
assert @base.generation_required?
end
test 'uniqueness_hash' do
assert_equal '4c703bbc05', @base.uniqueness_hash
end
it 'should be outdated' do
assert @base.outdated?
end
it 'should have correct filename' do
assert_equal File.join(@images_tmp_path, "#{@base.path}-s#{@base.uniqueness_hash}.png"), @base.filename
end
it "should return the 'ten-by-ten' image" do
assert_equal 'ten-by-ten', @base.image_for('ten-by-ten').name
assert @base.image_for('ten-by-ten').is_a?(Compass::SassExtensions::Sprites::Image)
end
%w(target hover active).each do |selector|
it "should have a #{selector}" do
assert @base.send(:"has_#{selector}?", 'ten-by-ten')
end
it "should return #{selector} image class" do
assert_equal "ten-by-ten_#{selector}", @base.image_for('ten-by-ten').send(:"#{selector}").name
end
it "should find file with '-' #{selector}" do
map = sprite_map_test(:seperator => '-')
map.images.each_index do |i|
if map.images[i].name != 'ten-by-ten'
name = map.images[i].name.gsub(/_/, '-')
map.images[i].stubs(:name).returns(name)
end
end
assert_equal "ten-by-ten-#{selector}", map.image_for('ten-by-ten').send(:"#{selector}").name
end
end
it "should generate sprite" do
@base.generate
assert File.exists?(@base.filename)
assert !@base.generation_required?
assert !@base.outdated?
end
it "should remove old sprite when generating new" do
@base.generate
file = @base.filename
assert File.exists?(file), "Original file does not exist"
file_to_remove = File.join(@images_tmp_path, 'selectors', 'ten-by-ten.png')
FileUtils.rm file_to_remove
assert !File.exists?(file_to_remove), "Failed to remove sprite file"
@base = sprite_map_test(@options)
@base.generate
assert !File.exists?(file), "Sprite file did not get removed"
end
test "should get correct relative_name" do
Compass.reset_configuration!
uri = 'foo/*.png'
other_folder = File.join(@images_tmp_path, '../other-temp')
FileUtils.mkdir_p other_folder
FileUtils.mkdir_p File.join(other_folder, 'foo')
%w(my bar).each do |file|
FileUtils.touch(File.join(other_folder, "foo/#{file}.png"))
end
config = Compass::Configuration::Data.new('config')
config.images_path = @images_tmp_path
config.sprite_load_path = [@images_tmp_path, other_folder]
Compass.add_configuration(config, "sprite_config")
assert_equal 'foo/my.png', Compass::SassExtensions::Sprites::SpriteMap.relative_name(File.join(other_folder, 'foo/my.png'))
FileUtils.rm_rf other_folder
end
test "should get correct relative_name for directories with similar names" do
Compass.reset_configuration!
uri = 'foo/*.png'
other_folder = File.join(@images_tmp_path, '../other-temp')
other_folder2 = File.join(@images_tmp_path, '../other-temp2')
FileUtils.mkdir_p other_folder
FileUtils.mkdir_p other_folder2
FileUtils.mkdir_p File.join(other_folder2, 'foo')
%w(my bar).each do |file|
FileUtils.touch(File.join(other_folder2, "foo/#{file}.png"))
end
config = Compass::Configuration::Data.new('config')
config.images_path = @images_tmp_path
config.sprite_load_path = [@images_tmp_path, other_folder, other_folder2]
Compass.add_configuration(config, "sprite_config")
assert_equal 'foo/my.png', Compass::SassExtensions::Sprites::SpriteMap.relative_name(File.join(other_folder2, 'foo/my.png'))
FileUtils.rm_rf other_folder
FileUtils.rm_rf other_folder2
end
test "should create map for nested" do
base = Compass::SassExtensions::Sprites::SpriteMap.from_uri OpenStruct.new(:value => 'nested/squares/*.png'), @base.instance_variable_get(:@evaluation_context), @options
assert_equal 'squares', base.name
assert_equal 'nested/squares', base.path
end
test "should have correct position on ten-by-ten" do
percent = Sass::Script::Number.new(50, ['%'])
base = sprite_map_test(@options.merge('selectors_ten_by_ten_position' => percent))
assert_equal percent, base.image_for('ten-by-ten').position
end
test 'gets name for sprite in search path' do
Compass.reset_configuration!
uri = 'foo/*.png'
other_folder = File.join(@images_tmp_path, '../other-temp')
FileUtils.mkdir_p other_folder
FileUtils.mkdir_p File.join(other_folder, 'foo')
%w(my bar).each do |file|
FileUtils.touch(File.join(other_folder, "foo/#{file}.png"))
end
config = Compass::Configuration::Data.new('config')
config.images_path = @images_tmp_path
config.sprite_load_path = [@images_tmp_path, other_folder]
Compass.add_configuration(config, "sprite_config")
image = Compass::SassExtensions::Sprites::Image.new(@base, "foo/my.png", {})
assert_equal File.join(other_folder, 'foo/my.png'), image.file
assert_equal 0, image.size
end
end
================================================
FILE: compass-style.org/.compass/config.rb
================================================
# Require any additional compass plugins here.
require 'susy'
require 'css-slideshow'
# Set this to the root of your project when deployed:
http_path = "/"
project_path = File.expand_path(File.join(File.dirname(__FILE__), '..'))
css_dir = "output/stylesheets"
sass_dir = "content/stylesheets"
images_dir = "assets/images"
javascripts_dir = "assets/javascripts"
fonts_dir = "assets/fonts"
http_javascripts_dir = "javascripts"
http_stylesheets_dir = "stylesheets"
http_images_dir = "images"
http_fonts_dir = "fonts"
# To enable relative paths to assets via compass helper functions. Uncomment:
# relative_assets = true
================================================
FILE: compass-style.org/.gitignore
================================================
bin
vendor
output
vendor/ruby
crash.log
tmp
.bundle
sync
.rvmrc
================================================
FILE: compass-style.org/.livereload
================================================
# Lines starting with pound sign (#) are ignored.
# additional extensions to monitor
#config.exts << 'haml'
# exclude files with NAMES matching this mask
#config.exclusions << '~*'
# exclude files with PATHS matching this mask (if the mask contains a slash)
#config.exclusions << '/excluded_dir/*'
# exclude files with PATHS matching this REGEXP
#config.exclusions << /somedir.*(ab){2,4}.(css|js)$/
# reload the whole page when .js changes
#config.apply_js_live = false
# reload the whole page when .css changes
#config.apply_css_live = false
# wait 100ms for more changes before reloading a page
#config.grace_period = 0.1
================================================
FILE: compass-style.org/Gemfile
================================================
source 'https://rubygems.org'
gem 'nanoc', '~> 3.4.2'
gem 'i18n'
gem 'adsf'
gem 'rb-inotify'
gem 'thin'
gem 'foreman'
gem 'rdiscount'
gem 'thor'
gem 'rack'
gem 'fssm'
gem 'mime-types'
gem 'nokogiri'
gem 'coderay'
gem 'haml'
gem 'rake'
gem 'activesupport', '~> 3.0.10', :require => 'active_support/inflector'
gem 'sass', "~> 3.3.0"
gem 'compass', :path => ".."
gem 'susy'
gem 'css-slideshow', "0.2.0"
gem 'json'
gem 'css_parser', "1.0.1"
gem 'rb-fsevent'
gem 'builder'
================================================
FILE: compass-style.org/Procfile
================================================
watch: bundle exec nanoc watch
view: bundle exec nanoc view -H thin
================================================
FILE: compass-style.org/README.markdown
================================================
# Compass documentation
* [About](#about)
* [Documentation setup](#documentation-setup)
* [Documentation project structure](#documentation-project-structure)
* [HOW-TOs](#how-tos)
If you want to work on a specific part of the docs, please let everyone know via the [Compass-devs google group](http://groups.google.com/group/compass-devs/browse_thread/thread/41dc723721a194f8).
---
## About
This is the documentation for Compass. Much of the documentation is read from the
Sass source files to keep the docs in-line with current state of the code as much as
possible.
If you're reading this, you might be thinking about helping to improve the Compass documentation by editing existing documentation or by adding new documentation.
There are two main kinds of documentation:
* Tutorials → Describe **how** to use Compass.
* Reference → Details about **what** Compass has.
It's possible and encouraged for related tutorials and reference documentation to
link to each other.
## Documentation setup
So you want to help documenting Compass?
Setting up the documentation for Compass is not super-easy, but it's pretty doable.
The Compass docs live in the source code of Compass. Not directly in the Sass files though: the documentation is a combination of inline comments and source code read directly from the Sass files, and hand-maintained documentation and examples. We use [nanoc](http://nanoc.stoneship.org/) to generate a static website, combined with some Ruby to read the Compass source.
The reasons for this setup are simple:
* to keep the documentation current, we need to read from the source code
* to read from the source code, we need to be in the source code
If you encounter any problems, there's usually some people around to help at #compass on freenode IRC.
### Prerequisites:
* a Github account, setup to be able to clone repos (see [GitHub Help](http://help.github.com/))
* [Git](http://git-scm.com/downloads) installed on your computer
* a basic knowledge of Git ([Pro Git](http://git-scm.com/book) is an excellent free guide)
Make sure that you have RubyGems v1.3.6 or greater:
```sh
$ gem -v
```
If that doesn't work, RubyGems is probably out of date, try:
```sh
$ (sudo) gem update --system
```
You will need the [Bundler](http://gembundler.com/) gem, so if you don't have it:
```sh
$ (sudo) gem install bundler
```
A list of the gems on your system can be accessed via `gem list`. Run `gem list bundler` to see if you have bundler installed.
### 1. Get your own copy of Compass (fork)
Make your own fork of Compass on Github by clicking the "Fork" button on [http://github.com/chriseppstein/compass](http://github.com/chriseppstein/compass), then go to your fork of Compass on GitHub. Your compass fork will be available at `http://github.com//compass` .
### 2. Directory setup
`git clone` your fork of the Compass repository:
```sh
$ git clone git@github.com:/compass.git
```
### 3. Bundler
If you haven't yet done so, install bundler:
```sh
$ (sudo) gem install bundler
```
Bundle the gems for this application:
```sh
$ cd compass-style.org
$ bundle install
```
### 3/4. Binstubs
If your bundler is still stuck with generating binstubs (an approach we
used before), check if there's a `.bundler` directory in
`compass-style.org`. If there is, delete it and try again. If you don't
know what we're talking about, then everything is fine, continue... :)
### 4. Compile the docs
First, make sure you're in the `compass-style.org` directory. To watch the folder for changes and to preview the site in your browser, run:
```sh
$ foreman start
```
Then go to [http://localhost:3000](http://localhost:3000) to view the site.
We use [foreman](https://github.com/ddollar/foreman) to combine two nanoc commands using a `Procfile`, which you'll find in `compass-style.org`. If you take a look a it, you'll see two processes, `watch` and `view`:
```sh
watch: bundle exec nanoc watch
view: bundle exec nanoc view -H thin
```
`nanoc watch` watches for changes and `nanoc view -H thin` previews the site using thin (rather than WEBrick, which it would use by default). We suggest you install [Growl](http://growl.info/) or [rb-inotify](https://github.com/nex3/rb-inotify) so you can receive notifications when the site is done compiling.
Your basic workflow might look like this:
1. run `foreman start`
1. open [http://localhost:3000](http://localhost:3000)
1. make changes in the project files (and save them)
1. wait for the notification that the compilation is complete
1. refresh the browser to see the changes
1. go to 3.
If you refresh the browser before the compilation is complete, nothing bad will happen, you just won't see the change until the compilation finishes (and you refresh again). That's because the site is compiling asynchronously.
Auto-compiling on file change might not be your thing. In that case, keep this process running in a separate terminal window:
```sh
$ bundle exec nanoc view -H thin
```
and run:
```sh
$ bundle exec nanoc (compile)
```
every time you want to compile the site and see the changes.
If this doesn't work for you, you could try nanoc's `aco` (or `autocompile`) command:
```sh
$ bundle exec nanoc aco -H thin
```
It compiles and previews the site in the browser (also at [http://localhost:3000](http://localhost:3000)), then recompiles it on each request. The difference from the previous approach is that the site is recompiled each time a page is requested, not when a file is changed. This approach is usually more sluggish because it's synchronous.
For convenience, all these commands are written as rake tasks:
```sh
$ rake watch # bundle execn nanoc watch
$ rake view # bundle exec nanoc view -H thin
$ rake compile # bundle exec nanoc (compile)
$ rake aco # bundle exec nanoc aco -H thin
```
if you choose not to use the Procfile approach.
It is recommended that you read the 5 minute [tutorial](http://nanoc.stoneship.org/tutorial/) on nanoc.
### 5. Commit your changes to your fork
When you're happy with the changes you made and you're ready to submit them, use `git add` to stage the changes, then commit them with:
```sh
$ git commit
```
When you're ready to push your changes to your Compass fork on GitHub, run:
```sh
$ git push -u origin
```
depending on which branch you want to push. Your changes are now reflected on your github repo. Go to Github and click the "Pull Request" button on top of your repo to notify Chris of changes. He will verify them and merge them into the master.
#### How to pull in new changes
Add the original Compass repository to your Git remotes:
```sh
$ git remote add chris git://github.com/chriseppstein/compass.git
```
Then get the new changes with fetch:
```sh
$ git fetch chris
```
And merge them with your local docs branch:
```sh
$ git merge chris
```
## Documentation project structure
.compass/config.rb
Compass configuration of the project.
content/
Content of the project.
content/reference/
Reference documentation.
content/examples/
Examples.
content/help/tutorials/
Tutorial documentation.
content/stylesheets/
Sass stylesheets for the project.
assets/css/
Third-party, plain old CSS files.
assets/images/
Images.
assets/javascripts/
JavaScript files.
layouts/
Layouts for the project.
layouts/partials/
Partials for the project.
lib/
Ruby code – helper code and Sass source inspection is done here.
## HOW-TOs
### How to Add an Asset
If you are adding an asset (e.g. image, CSS, JavaScript) place the file(s) in the appropriate directories under the `assets` directory.
### How to Add a New Example
(Again, make sure you're in the `compass-style.org` directory.)
We're using [Thor](https://github.com/wycats/thor) to generate examples and references. The command for generating examples is `generate:example`, you can see command's description and available options by running:
```sh
$ thor help generate:example
```
which produces:
```sh
Usage:
thor generate:example path/to/module
Options:
-t, [--title=TITLE] # Title of the example.
-d, [--description=DESCRIPTION] # Description of the example, which is shown below the link.
-m, [--mixin=MIXIN] # Name of the specific mixin in the module if the example isn't about the whole module.
Generates a new example.
```
All of these are optional and have reasonable defaults, you can use them when understand what exactly they are setting. They are all simple metadata values, so you can change them later on.
**Note**: When generating examples or references, Thor is searching for the appropriate
module stylesheet. If it doesn't find one, it raises an error and doesn't
generate anything. So before generating anything make sure the stylesheet exists and is
under `../frameworks/compass/stylesheets/compass/path/to/module` (relative to the `compass-style.org` directory). If the path confuses you, just take a few minutes to study how other modules are organized and you'll quickly get the hang of it.
Let's do an example:
```sh
$ thor generate:example typography/lists/inline-block-list
```
which produces the following output:
```
Generating /examples/compass/typography/lists/inline-block-list/
DIRECTORY content/examples/compass/typography/lists/inline-block-list/
CREATE content/examples/compass/typography/lists/inline-block-list.haml
CREATE content/examples/compass/typography/lists/inline-block-list/markup.haml
CREATE content/examples/compass/typography/lists/inline-block-list/stylesheet.scss
```
The command generated three files:
1. `inline-block-list.haml` → The main container, it contains example metadata
and description.
1. `markup.haml` → The markup for the example, it will be shown as HTML and as Haml and it's styled with `stylesheet.scss`.
1. `stylesheet.scss` → The style for the example, it will be shown as SCSS, Sass
and as CSS. This is the main file as it is demonstrating the module.
`markup.haml` and `stylesheet.scss` are pretty self-explanatory, but we might want take a look at `inline-block-list.haml`.
```
---
title: Inline Block List
description: How to use Inline Block List
framework: compass
stylesheet: compass/typography/lists/_inline-block-list.scss
example: true
---
- render "partials/example" do
%p Lorem ipsum dolor sit amet.
```
The stuff between `---` is called YAML front matter, it's describes example's metadata which is used to associate the example to the reference documentation.
If your example covers only a specific mixin, not the whole module, you can add
`mixin: ` to the metadata. This will display the example link right below
that mixin in the reference (otherwise, it will appear near the top, below the module
description).
After adding the example and adjusting the metadata, go to the reference page in your browser and you can verify that a link to the example has appeared.
### How to Add New Reference Documentation
Existing modules already have reference files, so you'll most likely be adding
reference files to new modules.
So we got a great idea for an awesome module, and after a lot of thinking we decided to name it `super-awesome-module`. The first step to adding a new module is creating the stylesheet. Let's say this will be a Compass CSS3 module, so we'll create a new file as `../frameworks/compass/stylesheets/compass/css3/_super-awesome-module.scss` (relative to the `compass-style.org` directory). Keep in mind that the comments inside those stylesheets are parsed with Markdown and output into the reference.
The easiest way to find out how you should write your stylesheet is to take a look at some existing modules. This module won't be very useful, but you'll get the point:
```scss
@import "shared";
// Super awesomeness variable.
$default-super-awesomeness : true !default;
// Super awesome mixin.
@mixin super-awesome {
@if $default-super-awesomeness {
$a: 5;
}
}
```
Now that we have a stylesheet, we can generate the reference for it using the
`generate:reference` command. We can first see what it does by running:
```sh
$ thor help generate:reference
```
which produces:
```sh
Usage:
thor generate:reference path/to/module
Options:
-t, [--title=TITLE] # Title of the reference.
Generate a reference page for the given module.
```
Now we can create a reference file for our new module:
```sh
$ thor generate:reference css3/super-awesome-module
```
Which produces the following output:
```
Generating /reference/compass/css3/super-awesome-module/
DIRECTORY content/reference/compass/css3/super-awesome-module/
CREATE content/reference/compass/css3/super-awesome-module.haml
```
If we open `super-awesome-module.haml`, we can see our reference template:
```
---
title: Compass Super Awesome Module
crumb: Super Awesome Module
framework: compass
stylesheet: compass/css3/_super-awesome-module.scss
layout: core
classnames:
- reference
- core
---
- render "reference" do
%p Lorem ipsum dolor sit amet.
```
If `title` and `crumb` are the way you want them to be, your metadata should be good to go. Check the reference in your browser (it should be listed as a module in CSS3), if the style appears broken, take a look at the metadata of sibling stylesheets and adjust yours accordingly. If everything looks fine you can start writing the module's description below.
Unlike what you might have guessed, the reference file only holds the main
description of the module. Descriptions of specific variables, functions and
mixins should be written as comments in the stylesheet file.
Happy documenting!
================================================
FILE: compass-style.org/Rakefile
================================================
require "bundler"
Bundler.setup
require "rake"
desc "Watch the site for changes."
task :watch do
sh "nanoc watch"
end
desc "Compile the site."
task :compile do
sh "nanoc compile"
end
desc "View the site in a browser."
task :view do
sh "nanoc view -H thin"
end
desc "View the site in a browser with live updating (sluggish)."
task :aco do
sh "nanoc aco -H thin"
end
================================================
FILE: compass-style.org/Rules
================================================
#!/usr/bin/env ruby
require 'sass'
require 'compass'
Compass.add_configuration "#{File.dirname(__FILE__)}/.compass/config.rb"
SITE_ROOT = ""
compile '/assets/*/' do
nil
end
['markup', 'stylesheet', 'background'].each do |ex_file|
compile "/examples/*/#{ex_file}/" do
snapshot :raw
nil
end
end
compile '/' do
filter :haml, :ugly => true
layout item[:layout] ? item[:layout] : "main"
end
compile '/search-data/' do
filter :erb
end
compile '/examples/*/' do
filter :haml, :ugly => true
filter :highlight
layout item[:layout] ? item[:layout] : "example"
end
sass_options = Compass.sass_engine_options
(0..5).each do |i|
compile("/stylesheets/#{'*/' * i}_*/") {nil}
end
compile '/stylesheets/*' do
filter :sass, sass_options.merge(:syntax => item[:extension].to_sym)
end
compile '/reference/*/' do
filter :haml, :ugly => true
filter :highlight
layout item[:layout] ? item[:layout] : "main"
end
compile '/posts/*/' do
filter :erb
filter :rdiscount if item[:extension] == "markdown"
layout 'post'
end
compile "/blog/atom/" do
filter :haml, :attr_wrapper => '"'
end
compile 'sitemap' do
filter :erb
end
compile '*' do
if item[:extension] == "markdown"
filter :erb
filter :rdiscount
elsif item[:extension] == "haml"
filter :haml, :ugly => true
end
layout item[:layout] ? item[:layout] : "main"
end
route 'sitemap' do
item.identifier.chop + '.xml'
end
route "/blog/atom/" do
"/blog/atom.xml"
end
route '/search-data/' do
"#{SITE_ROOT}/javascripts"+item.identifier[0..-2]+".js"
end
(0..5).each do |i|
route("/stylesheets/#{'*/' * i}_*/") {nil}
end
route '/assets/htaccess/' do
"#{SITE_ROOT}/.htaccess"
end
route '/assets/css/*/' do
"#{SITE_ROOT}/stylesheets"+item.identifier.chop[11..-1]
end
route '/assets/images/*/' do
SITE_ROOT+item.identifier.chop[7..-1]
end
route '/assets/javascripts/*/' do
SITE_ROOT+item.identifier.chop[7..-1]
end
route '/assets/fonts/*/' do
SITE_ROOT+item.identifier.chop[7..-1]
end
route '/stylesheets/*/' do
# don't generate a directory like we do for HTML files
SITE_ROOT+item.identifier.chop + '.css'
end
route '/posts/*/' do
if item[:draft]
puts "Skipping Draft post: #{item.identifier}"
nil
elsif item.identifier =~ %r{^/posts/(\d{4})-(\d{2})-(\d{2})-(.*)/$}
"/blog/#{$1}/#{$2}/#{$3}/#{$4}/index.html"
else
puts "WARNING: malformed post name: #{item.identifier}"
nil
end
end
%w(markup stylesheet background).each do |ex_file|
route "/examples/*/#{ex_file}/" do
nil
end
end
route '*' do
SITE_ROOT+item.identifier + 'index.html'
end
layout '*', :haml, :ugly => true
================================================
FILE: compass-style.org/assets/htaccess
================================================
RedirectMatch 301 /docs/$ /reference/compass/
RedirectMatch 301 /docs/tutorials/(.*) /help/tutorials/$1
RedirectMatch 301 /docs/(.*) /$1
RedirectMatch 301 /reference/$ /reference/compass/
================================================
FILE: compass-style.org/assets/javascripts/fixups.js
================================================
$(function(){
$('span.color').each(function(i,e){
e = $(e);
e.after('');
});
$('span.arg[data-default-value]').each(function(i,e){
e = $(e);
e.attr("title", "Defaults to: " + e.attr("data-default-value"))
});
});
/*;(function()
{
typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;
function Brush(){};
Brush.prototype = new SyntaxHighlighter.Highlighter();
Brush.aliases = ['sass', 'scss', 'css', 'html'];
SyntaxHighlighter.brushes.Sass = Brush;
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
})();*/
================================================
FILE: compass-style.org/assets/javascripts/install.js
================================================
function showInstallCommand() {
var cmd = $("#existence").val();
var commands = [];
var notes = [];
var project_name = "<myproject>";
var can_be_bare = true;
var in_working_dir = false;
var use_bundler = false;
if ($("#app-type").val() != "rails") {
commands.push("$ gem install compass");
}
if (cmd == "init") {
commands.push("$ cd " + project_name);
in_working_dir = true
project_name = ".";
$(".creating").hide();
} else {
$(".creating").show();
if ($("#project_name").val() != "")
project_name = $("#project_name").val();
}
if ($("#app-type").val() == "rails") {
notes.push("
Rails 2.3 and 3.0 users require additional installation steps. For full rails installation and upgrade instructions please refer to the compass-rails README.
Note: Values indicated by <> are placeholders. Change them to suit your needs.");
}
$("#steps").html(instructions + notes.join(""));
}
function attachMadlibBehaviors() {
$("#app-type").change(function(event) {
var val = $(event.target).val();
if (val == "other") {
$("#options").val("customized");
$(".madlib").addClass("customizable");
} else if (val == "rails") {
$("#options").val("default");
$(".madlib").removeClass("customizable");
} else {
$(".madlib").addClass("customizable");
}
});
$("#existence, #app-type, #framework, #syntax, #options").change(showInstallCommand);
$(".madlib input").keyup(function(){setTimeout(showInstallCommand, 0.1)});
}
function setupMadlib() {
attachMadlibBehaviors();
showInstallCommand();
}
$(setupMadlib);
================================================
FILE: compass-style.org/assets/javascripts/jquery.cookie.js
================================================
/**
* Cookie plugin
*
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/
/**
* Create a cookie with the given name and value and other optional parameters.
*
* @example $.cookie('the_cookie', 'the_value');
* @desc Set the value of a cookie.
* @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
* @desc Create a cookie with all available options.
* @example $.cookie('the_cookie', 'the_value');
* @desc Create a session cookie.
* @example $.cookie('the_cookie', null);
* @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
* used when the cookie was set.
*
* @param String name The name of the cookie.
* @param String value The value of the cookie.
* @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
* @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
* If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
* If set to null or omitted, the cookie will be a session cookie and will not be retained
* when the the browser exits.
* @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
* @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
* @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
* require a secure protocol (like HTTPS).
* @type undefined
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
*/
/**
* Get the value of a cookie with the given name.
*
* @example $.cookie('the_cookie');
* @desc Get the value of a cookie.
*
* @param String name The name of the cookie.
* @return The value of the cookie.
* @type String
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
*/
jQuery.cookie = function(name, value, options) {
if (typeof value != 'undefined') { // name and value given, set cookie
options = options || {};
if (value === null) {
value = '';
options.expires = -1;
}
var expires = '';
if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
var date;
if (typeof options.expires == 'number') {
date = new Date();
date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
} else {
date = options.expires;
}
expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
}
// CAUTION: Needed to parenthesize options.path and options.domain
// in the following expressions, otherwise they evaluate to undefined
// in the packed version for some reason...
var path = options.path ? '; path=' + (options.path) : '';
var domain = options.domain ? '; domain=' + (options.domain) : '';
var secure = options.secure ? '; secure' : '';
document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
} else { // only name given, get cookie
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
};
================================================
FILE: compass-style.org/assets/javascripts/jquery.url.packed.js
================================================
jQuery.url=function(){var segments={};var parsed={};var options={url:window.location,strictMode:false,key:["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],q:{name:"queryKey",parser:/(?:^|&)([^&=]*)=?([^&]*)/g},parser:{strict:/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/}};var parseUri=function(){str=decodeURI(options.url);var m=options.parser[options.strictMode?"strict":"loose"].exec(str);var uri={};var i=14;while(i--){uri[options.key[i]]=m[i]||""}uri[options.q.name]={};uri[options.key[12]].replace(options.q.parser,function($0,$1,$2){if($1){uri[options.q.name][$1]=$2}});return uri};var key=function(key){if(!parsed.length){setUp()}if(key=="base"){if(parsed.port!==null&&parsed.port!==""){return parsed.protocol+"://"+parsed.host+":"+parsed.port+"/"}else{return parsed.protocol+"://"+parsed.host+"/"}}return(parsed[key]==="")?null:parsed[key]};var param=function(item){if(!parsed.length){setUp()}return(parsed.queryKey[item]===null)?null:parsed.queryKey[item]};var setUp=function(){parsed=parseUri();getSegments()};var getSegments=function(){var p=parsed.path;segments=[];segments=parsed.path.length==1?{}:(p.charAt(p.length-1)=="/"?p.substring(1,p.length-1):path=p.substring(1)).split("/")};return{setMode:function(mode){strictMode=mode=="strict"?true:false;return this},setUrl:function(newUri){options.url=newUri===undefined?window.location:newUri;setUp();return this},segment:function(pos){if(!parsed.length){setUp()}if(pos===undefined){return segments.length}return(segments[pos]===""||segments[pos]===undefined)?null:segments[pos]},attr:key,param:param}}();
================================================
FILE: compass-style.org/assets/javascripts/placeholder.js
================================================
(function($) {
$.fn.replaceholder = function(options) {
var $placeholder;
(this.length > 0) ? $this = $(this) : $this = $('input[placeholder]');
return $this.each(function() {
settings = jQuery.extend(options);
var $placeholder = $(this);
if ($placeholder.length > 0) {
var attrPh = $placeholder.attr('placeholder');
$placeholder.attr('value', attrPh);
$placeholder.bind('focus', function() {
var $this = $(this);
if($this.val() === attrPh)
$this.val('').removeClass('placeholder');
}).bind('blur', function() {
var $this = $(this);
if($this.val() === '')
$this.val(attrPh).addClass('placeholder');
});
}
});
};
})(jQuery);
jQuery(function($){
$(document).ready(function(){
if (!Modernizr.input.placeholder) { $("input[placeholder], textarea[placeholder]").replaceholder() }
})
})
================================================
FILE: compass-style.org/assets/javascripts/shAutoloader.js
================================================
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
eval(function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(2(){1 h=5;h.I=2(){2 n(c,a){4(1 d=0;d)/gi,
right: /(<|<)\/\s*style\s*(>|>)/gi
});
};
Brush.prototype = new SyntaxHighlighter.Highlighter();
Brush.aliases = ['css'];
SyntaxHighlighter.brushes.CSS = Brush;
// CommonJS
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
})();
================================================
FILE: compass-style.org/assets/javascripts/shBrushPlain.js
================================================
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
;(function()
{
// CommonJS
typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;
function Brush()
{
};
Brush.prototype = new SyntaxHighlighter.Highlighter();
Brush.aliases = ['text', 'plain', 'haml'];
SyntaxHighlighter.brushes.Plain = Brush;
// CommonJS
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
})();
================================================
FILE: compass-style.org/assets/javascripts/shBrushSass.js
================================================
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
;(function()
{
// CommonJS
typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;
function Brush()
{
function getKeywordsCSS(str)
{
return '\\b([a-z_]|)' + str.replace(/ /g, '(?=:)\\b|\\b([a-z_\\*]|\\*|)') + '(?=:)\\b';
};
function getValuesCSS(str)
{
return '\\b' + str.replace(/ /g, '(?!-)(?!:)\\b|\\b()') + '\:\\b';
};
var keywords = 'ascent azimuth background-attachment background-color background-image background-position ' +
'background-repeat background baseline bbox border-collapse border-color border-spacing border-style border-top ' +
'border-right border-bottom border-left border-top-color border-right-color border-bottom-color border-left-color ' +
'border-top-style border-right-style border-bottom-style border-left-style border-top-width border-right-width ' +
'border-bottom-width border-left-width border-width border bottom cap-height caption-side centerline clear clip color ' +
'content counter-increment counter-reset cue-after cue-before cue cursor definition-src descent direction display ' +
'elevation empty-cells float font-size-adjust font-family font-size font-stretch font-style font-variant font-weight font ' +
'height left letter-spacing line-height list-style-image list-style-position list-style-type list-style margin-top ' +
'margin-right margin-bottom margin-left margin marker-offset marks mathline max-height max-width min-height min-width orphans ' +
'outline-color outline-style outline-width outline overflow padding-top padding-right padding-bottom padding-left padding page ' +
'page-break-after page-break-before page-break-inside pause pause-after pause-before pitch pitch-range play-during position ' +
'quotes right richness size slope src speak-header speak-numeral speak-punctuation speak speech-rate stemh stemv stress ' +
'table-layout text-align top text-decoration text-indent text-shadow text-transform unicode-bidi unicode-range units-per-em ' +
'vertical-align visibility voice-family volume white-space widows width widths word-spacing x-height z-index zoom';
var values = 'above absolute all always aqua armenian attr aural auto avoid baseline behind below bidi-override black blink block blue bold bolder '+
'both bottom braille capitalize caption center center-left center-right circle close-quote code collapse compact condensed '+
'continuous counter counters crop cross crosshair cursive dashed decimal decimal-leading-zero digits disc dotted double '+
'embed embossed e-resize expanded extra-condensed extra-expanded fantasy far-left far-right fast faster fixed format fuchsia '+
'gray green groove handheld hebrew help hidden hide high higher icon inline-table inline inset inside invert italic '+
'justify landscape large larger left-side left leftwards level lighter lime line-through list-item local loud lower-alpha '+
'lowercase lower-greek lower-latin lower-roman lower low ltr marker maroon medium message-box middle mix move narrower '+
'navy ne-resize no-close-quote none no-open-quote no-repeat normal nowrap n-resize nw-resize oblique olive once open-quote outset '+
'outside overline pointer portrait pre print projection purple red relative repeat repeat-x repeat-y rgb ridge right right-side '+
'rightwards rtl run-in screen scroll semi-condensed semi-expanded separate se-resize show silent silver slower slow '+
'small small-caps small-caption smaller soft solid speech spell-out square s-resize static status-bar sub super sw-resize '+
'table-caption table-cell table-column table-column-group table-footer-group table-header-group table-row table-row-group teal '+
'text-bottom text-top thick thin top transparent tty tv ultra-condensed ultra-expanded underline upper-alpha uppercase upper-latin '+
'upper-roman url visible wait white wider w-resize x-fast x-high x-large x-loud x-low x-slow x-small x-soft xx-large xx-small yellow';
var fonts = '[mM]onospace [tT]ahoma [vV]erdana [aA]rial [hH]elvetica [sS]ans-serif [sS]erif [cC]ourier mono sans serif';
var statements = '!important !default';
var preprocessors = 'import extend debug warn if for while mixin include';
var r = SyntaxHighlighter.regexLib;
var getKeywordsPrependedBy = function(keywords, by)
{
str = keywords
.replace(/^\s+|\s+$/g, '')
.replace(/\s+/g, '|' + by + '\\b')
.replace(/^/, by + '\\b')
;
return '(?:' + str + ')\\b';
}
this.regexList = [
{ regex: r.multiLineCComments, css: 'comments' }, // multiline comments
{ regex: r.singleLineCComments, css: 'comments' }, // singleline comments
{ regex: r.doubleQuotedString, css: 'string' }, // double quoted strings
{ regex: r.singleQuotedString, css: 'string' }, // single quoted strings
{ regex: /\#[a-fA-F0-9]{3,6}/g, css: 'value' }, // html colors
{ regex: /\b(-?\d+)(\.\d+)?(px|em|pt|\:|\%|)\b/g, css: 'value' }, // sizes
{ regex: /(\$|!)\w+/g, css: 'variable' }, // variables
{ regex: new RegExp(this.getKeywords(statements), 'g'), css: 'color3' }, // statements
{ regex: new RegExp(getKeywordsPrependedBy(preprocessors, '@'), 'g'), css: 'preprocessor' }, // preprocessors
{ regex: new RegExp('(^|\\n)\\s*=.*', 'g'), css: 'functions' }, // short mixin declarations
{ regex: new RegExp('(^|\\n)\\s*\\+.*', 'g'), css: 'functions' }, // short mixin call
{ regex: new RegExp('&', 'g'), css: 'keyword' }, // &
{ regex: new RegExp('#(\\w|-|_)+', 'g'), css: 'color2' }, // ids
{ regex: new RegExp('(\\.(\\w|-|_)+)', 'g'), css: 'color4' }, // classes
{ regex: new RegExp(getKeywordsCSS(keywords), 'gm'), css: 'keyword' }, // keywords
{ regex: new RegExp(getKeywordsPrependedBy(keywords, ':'), 'g'), css: 'keyword' }, // :keyword value
{ regex: new RegExp(getValuesCSS(values), 'g'), css: 'value' }, // values
{ regex: new RegExp(this.getKeywords(fonts), 'g'), css: 'color1' } // fonts
];
};
Brush.prototype = new SyntaxHighlighter.Highlighter();
Brush.aliases = ['sass', 'scss'];
SyntaxHighlighter.brushes.Sass = Brush;
// CommonJS
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
})();
================================================
FILE: compass-style.org/assets/javascripts/shBrushScss.js
================================================
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
;(function()
{
// CommonJS
typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;
function Brush()
{
function getKeywordsSCSS(str)
{
return '\\b([a-z_]|)' + str.replace(/ /g, '(?=:)\\b|\\b([a-z_\\*]|\\*|)') + '(?=:)\\b';
};
function getValuesSCSS(str)
{
return '\\b' + str.replace(/ /g, '(?!-)(?!:)\\b|\\b()') + '\:\\b';
};
var keywords = 'ascent azimuth background-attachment background-color background-image background-position ' +
'background-repeat background baseline bbox border-collapse border-color border-spacing border-style border-top ' +
'border-right border-bottom border-left border-top-color border-right-color border-bottom-color border-left-color ' +
'border-top-style border-right-style border-bottom-style border-left-style border-top-width border-right-width ' +
'border-bottom-width border-left-width border-width border bottom cap-height caption-side centerline clear clip color ' +
'content counter-increment counter-reset cue-after cue-before cue cursor definition-src descent direction display ' +
'elevation empty-cells float font-size-adjust font-family font-size font-stretch font-style font-variant font-weight font ' +
'height left letter-spacing line-height list-style-image list-style-position list-style-type list-style margin-top ' +
'margin-right margin-bottom margin-left margin marker-offset marks mathline max-height max-width min-height min-width orphans ' +
'outline-color outline-style outline-width outline overflow padding-top padding-right padding-bottom padding-left padding page ' +
'page-break-after page-break-before page-break-inside pause pause-after pause-before pitch pitch-range play-during position ' +
'quotes right richness size slope src speak-header speak-numeral speak-punctuation speak speech-rate stemh stemv stress ' +
'table-layout text-align top text-decoration text-indent text-shadow text-transform unicode-bidi unicode-range units-per-em ' +
'vertical-align visibility voice-family volume white-space widows width widths word-spacing x-height z-index';
var values = 'above absolute all always aqua armenian attr aural auto avoid baseline behind below bidi-override black blink block blue bold bolder '+
'both bottom braille capitalize caption center center-left center-right circle close-quote code collapse compact condensed '+
'continuous counter counters crop cross crosshair cursive dashed decimal decimal-leading-zero default digits disc dotted double '+
'embed embossed e-resize expanded extra-condensed extra-expanded fantasy far-left far-right fast faster fixed format fuchsia '+
'gray green groove handheld hebrew help hidden hide high higher icon inline-table inline inset inside invert italic '+
'justify landscape large larger left-side left leftwards level lighter lime line-through list-item local loud lower-alpha '+
'lowercase lower-greek lower-latin lower-roman lower low ltr marker maroon medium message-box middle mix move narrower '+
'navy ne-resize no-close-quote none no-open-quote no-repeat normal nowrap n-resize nw-resize oblique olive once open-quote outset '+
'outside overline pointer portrait pre print projection purple red relative repeat repeat-x repeat-y rgb ridge right right-side '+
'rightwards rtl run-in screen scroll semi-condensed semi-expanded separate se-resize show silent silver slower slow '+
'small small-caps small-caption smaller soft solid speech spell-out square s-resize static status-bar sub super sw-resize '+
'table-caption table-cell table-column table-column-group table-footer-group table-header-group table-row table-row-group teal '+
'text-bottom text-top thick thin top transparent tty tv ultra-condensed ultra-expanded underline upper-alpha uppercase upper-latin '+
'upper-roman url visible wait white wider w-resize x-fast x-high x-large x-loud x-low x-slow x-small x-soft xx-large xx-small yellow';
var fonts = '[mM]onospace [tT]ahoma [vV]erdana [aA]rial [hH]elvetica [sS]ans-serif [sS]erif [cC]ourier mono sans serif';
this.regexList = [
{ regex: SyntaxHighlighter.regexLib.multiLineCComments, css: 'comments' }, // multiline comments
{ regex: SyntaxHighlighter.regexLib.doubleQuotedString, css: 'string' }, // double quoted strings
{ regex: SyntaxHighlighter.regexLib.singleQuotedString, css: 'string' }, // single quoted strings
{ regex: /\#[a-fA-F0-9]{3,6}/g, css: 'value' }, // html colors
{ regex: /(-?\d+)(\.\d+)?(px|em|pt|\:|\%|)/g, css: 'value' }, // sizes
{ regex: /!important/g, css: 'color3' }, // !important
{ regex: new RegExp(getKeywordsSCSS(keywords), 'gm'), css: 'keyword' }, // keywords
{ regex: new RegExp(getValuesSCSS(values), 'g'), css: 'value' }, // values
{ regex: new RegExp(this.getKeywords(fonts), 'g'), css: 'color1' } // fonts
];
this.forHtmlScript({
left: /(<|<)\s*style.*?(>|>)/gi,
right: /(<|<)\/\s*style\s*(>|>)/gi
});
};
Brush.prototype = new SyntaxHighlighter.Highlighter();
Brush.aliases = ['scss'];
SyntaxHighlighter.brushes.SCSS = Brush;
// CommonJS
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
})();
================================================
FILE: compass-style.org/assets/javascripts/shBrushXml.js
================================================
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
;(function()
{
// CommonJS
typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;
function Brush()
{
function process(match, regexInfo)
{
var constructor = SyntaxHighlighter.Match,
code = match[0],
tag = new XRegExp('(<|<)[\\s\\/\\?]*(?[:\\w-\\.]+)', 'xg').exec(code),
result = []
;
if (match.attributes != null)
{
var attributes,
regex = new XRegExp('(? [\\w:\\-\\.]+)' +
'\\s*=\\s*' +
'(? ".*?"|\'.*?\'|\\w+)',
'xg');
while ((attributes = regex.exec(code)) != null)
{
result.push(new constructor(attributes.name, match.index + attributes.index, 'color1'));
result.push(new constructor(attributes.value, match.index + attributes.index + attributes[0].indexOf(attributes.value), 'string'));
}
}
if (tag != null)
result.push(
new constructor(tag.name, match.index + tag[0].indexOf(tag.name), 'keyword')
);
return result;
}
this.regexList = [
{ regex: new XRegExp('(\\<|<)\\!\\[[\\w\\s]*?\\[(.|\\s)*?\\]\\](\\>|>)', 'gm'), css: 'color2' }, //
{ regex: SyntaxHighlighter.regexLib.xmlComments, css: 'comments' }, //
{ regex: new XRegExp('(<|<)[\\s\\/\\?]*(\\w+)(?.*?)[\\s\\/\\?]*(>|>)', 'sg'), func: process }
];
};
Brush.prototype = new SyntaxHighlighter.Highlighter();
Brush.aliases = ['xml', 'xhtml', 'xslt', 'html'];
SyntaxHighlighter.brushes.Xml = Brush;
// CommonJS
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
})();
================================================
FILE: compass-style.org/assets/javascripts/shCore.js
================================================
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
eval(function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('K M;I(M)1S 2U("2a\'t 4k M 4K 2g 3l 4G 4H");(6(){6 r(f,e){I(!M.1R(f))1S 3m("3s 15 4R");K a=f.1w;f=M(f.1m,t(f)+(e||""));I(a)f.1w={1m:a.1m,19:a.19?a.19.1a(0):N};H f}6 t(f){H(f.1J?"g":"")+(f.4s?"i":"")+(f.4p?"m":"")+(f.4v?"x":"")+(f.3n?"y":"")}6 B(f,e,a,b){K c=u.L,d,h,g;v=R;5K{O(;c--;){g=u[c];I(a&g.3r&&(!g.2p||g.2p.W(b))){g.2q.12=e;I((h=g.2q.X(f))&&h.P===e){d={3k:g.2b.W(b,h,a),1C:h};1N}}}}5v(i){1S i}5q{v=11}H d}6 p(f,e,a){I(3b.Z.1i)H f.1i(e,a);O(a=a||0;a-1},3d:6(g){e+=g}};c1&&p(e,"")>-1){a=15(J.1m,n.Q.W(t(J),"g",""));n.Q.W(f.1a(e.P),a,6(){O(K c=1;c<14.L-2;c++)I(14[c]===1d)e[c]=1d})}I(J.1w&&J.1w.19)O(K b=1;be.P&&J.12--}H e};I(!D)15.Z.1A=6(f){(f=n.X.W(J,f))&&J.1J&&!f[0].L&&J.12>f.P&&J.12--;H!!f};1r.Z.1C=6(f){M.1R(f)||(f=15(f));I(f.1J){K e=n.1C.1p(J,14);f.12=0;H e}H f.X(J)};1r.Z.Q=6(f,e){K a=M.1R(f),b,c;I(a&&1j e.58()==="3f"&&e.1i("${")===-1&&y)H n.Q.1p(J,14);I(a){I(f.1w)b=f.1w.19}Y f+="";I(1j e==="6")c=n.Q.W(J,f,6(){I(b){14[0]=1f 1r(14[0]);O(K d=0;dd.L-3;){i=1r.Z.1a.W(g,-1)+i;g=1Q.3i(g/10)}H(g?d[g]||"":"$")+i}Y{g=+i;I(g<=d.L-3)H d[g];g=b?p(b,i):-1;H g>-1?d[g+1]:h}})})}I(a&&f.1J)f.12=0;H c};1r.Z.1e=6(f,e){I(!M.1R(f))H n.1e.1p(J,14);K a=J+"",b=[],c=0,d,h;I(e===1d||+e<0)e=5D;Y{e=1Q.3i(+e);I(!e)H[]}O(f=M.3c(f);d=f.X(a);){I(f.12>c){b.U(a.1a(c,d.P));d.L>1&&d.P=e)1N}f.12===d.P&&f.12++}I(c===a.L){I(!n.1A.W(f,"")||h)b.U("")}Y b.U(a.1a(c));H b.L>e?b.1a(0,e):b};M.1h(/\\(\\?#[^)]*\\)/,6(f){H n.1A.W(A,f.2S.1a(f.P+f[0].L))?"":"(?:)"});M.1h(/\\((?!\\?)/,6(){J.19.U(N);H"("});M.1h(/\\(\\?<([$\\w]+)>/,6(f){J.19.U(f[1]);J.2N=R;H"("});M.1h(/\\\\k<([\\w$]+)>/,6(f){K e=p(J.19,f[1]);H e>-1?"\\\\"+(e+1)+(3R(f.2S.3a(f.P+f[0].L))?"":"(?:)"):f[0]});M.1h(/\\[\\^?]/,6(f){H f[0]==="[]"?"\\\\b\\\\B":"[\\\\s\\\\S]"});M.1h(/^\\(\\?([5A]+)\\)/,6(f){J.3d(f[1]);H""});M.1h(/(?:\\s+|#.*)+/,6(f){H n.1A.W(A,f.2S.1a(f.P+f[0].L))?"":"(?:)"},M.1B,6(){H J.2K("x")});M.1h(/\\./,6(){H"[\\\\s\\\\S]"},M.1B,6(){H J.2K("s")})})();1j 2e!="1d"&&(2e.M=M);K 1v=6(){6 r(a,b){a.1l.1i(b)!=-1||(a.1l+=" "+b)}6 t(a){H a.1i("3e")==0?a:"3e"+a}6 B(a){H e.1Y.2A[t(a)]}6 p(a,b,c){I(a==N)H N;K d=c!=R?a.3G:[a.2G],h={"#":"1c",".":"1l"}[b.1o(0,1)]||"3h",g,i;g=h!="3h"?b.1o(1):b.5u();I((a[h]||"").1i(g)!=-1)H a;O(a=0;d&&a\'+c+"17>"});H a}6 n(a,b){a.1e("\\n");O(K c="",d=0;d<50;d++)c+=" ";H a=v(a,6(h){I(h.1i("\\t")==-1)H h;O(K g=0;(g=h.1i("\\t"))!=-1;)h=h.1o(0,g)+c.1o(0,b-g%b)+h.1o(g+1,h.L);H h})}6 x(a){H a.Q(/^\\s+|\\s+$/g,"")}6 D(a,b){I(a.Pb.P)H 1;Y I(a.Lb.L)H 1;H 0}6 y(a,b){6 c(k){H k[0]}O(K d=N,h=[],g=b.2D?b.2D:c;(d=b.1I.X(a))!=N;){K i=g(d,b);I(1j i=="3f")i=[1f e.2L(i,d.P,b.23)];h=h.1O(i)}H h}6 E(a){K b=/(.*)((&1G;|&1y;).*)/;H a.Q(e.3A.3M,6(c){K d="",h=N;I(h=b.X(c)){c=h[1];d=h[2]}H\'\'+c+""+d})}6 z(){O(K a=1E.36("1k"),b=[],c=0;c<1z 4I="1Z://2y.3L.3K/4L/5L"><3J><4N 1Z-4M="5G-5M" 6K="2O/1z; 6J=6I-8" /><1t>6L 1v1t>3J><3B 1L="25-6M:6Q,6P,6O,6N-6F;6y-2f:#6x;2f:#6w;25-22:6v;2O-3D:3C;">1v3v 3.0.76 (72 73 3x)1Z://3u.2w/1v70 17 6U 71.6T 6X-3x 6Y 6D.6t 61 60 J 1k, 5Z 5R 5V <2R/>5U 5T 5S!3B>1z>\'}},1Y:{2j:N,2A:{}},1U:{},3A:{6n:/\\/\\*[\\s\\S]*?\\*\\//2c,6m:/\\/\\/.*$/2c,6l:/#.*$/2c,6k:/"([^\\\\"\\n]|\\\\.)*"/g,6o:/\'([^\\\\\'\\n]|\\\\.)*\'/g,6p:1f M(\'"([^\\\\\\\\"]|\\\\\\\\.)*"\',"3z"),6s:1f M("\'([^\\\\\\\\\']|\\\\\\\\.)*\'","3z"),6q:/(&1y;|<)!--[\\s\\S]*?--(&1G;|>)/2c,3M:/\\w+:\\/\\/[\\w-.\\/?%&=:@;]*/g,6a:{18:/(&1y;|<)\\?=?/g,1b:/\\?(&1G;|>)/g},69:{18:/(&1y;|<)%=?/g,1b:/%(&1G;|>)/g},6d:{18:/(&1y;|<)\\s*1k.*?(&1G;|>)/2T,1b:/(&1y;|<)\\/\\s*1k\\s*(&1G;|>)/2T}},16:{1H:6(a){6 b(i,k){H e.16.2o(i,k,e.13.1x[k])}O(K c=\'\',d=e.16.2x,h=d.2X,g=0;g";H c},2o:6(a,b,c){H\'<2W>\'+c+"2W>"},2b:6(a){K b=a.1F,c=b.1l||"";b=B(p(b,".20",R).1c);K d=6(h){H(h=15(h+"6f(\\\\w+)").X(c))?h[1]:N}("6g");b&&d&&e.16.2x[d].2B(b);a.3N()},2x:{2X:["21","2P"],21:{1H:6(a){I(a.V("2l")!=R)H"";K b=a.V("1t");H e.16.2o(a,"21",b?b:e.13.1x.21)},2B:6(a){a=1E.6j(t(a.1c));a.1l=a.1l.Q("47","")}},2P:{2B:6(){K a="68=0";a+=", 18="+(31.30-33)/2+", 32="+(31.2Z-2Y)/2+", 30=33, 2Z=2Y";a=a.Q(/^,/,"");a=1P.6Z("","38",a);a.2C();K b=a.1E;b.6W(e.13.1x.37);b.6V();a.2C()}}}},35:6(a,b){K c;I(b)c=[b];Y{c=1E.36(e.13.34);O(K d=[],h=0;h(.*?))\\\\]$"),s=1f M("(?<27>[\\\\w-]+)\\\\s*:\\\\s*(?<1T>[\\\\w-%#]+|\\\\[.*?\\\\]|\\".*?\\"|\'.*?\')\\\\s*;?","g");(j=s.X(k))!=N;){K o=j.1T.Q(/^[\'"]|[\'"]$/g,"");I(o!=N&&m.1A(o)){o=m.X(o);o=o.2V.L>0?o.2V.1e(/\\s*,\\s*/):[]}l[j.27]=o}g={1F:g,1n:C(i,l)};g.1n.1D!=N&&d.U(g)}H d},1M:6(a,b){K c=J.35(a,b),d=N,h=e.13;I(c.L!==0)O(K g=0;g")==o-3){m=m.4h(0,o-3);s=R}l=s?m:l}I((i.1t||"")!="")k.1t=i.1t;k.1D=j;d.2Q(k);b=d.2F(l);I((i.1c||"")!="")b.1c=i.1c;i.2G.74(b,i)}}},2E:6(a){w(1P,"4k",6(){e.1M(a)})}};e.2E=e.2E;e.1M=e.1M;e.2L=6(a,b,c){J.1T=a;J.P=b;J.L=a.L;J.23=c;J.1V=N};e.2L.Z.1q=6(){H J.1T};e.4l=6(a){6 b(j,l){O(K m=0;md)1N;Y I(g.P==c.P&&g.L>c.L)a[b]=N;Y I(g.P>=c.P&&g.P\'+c+""},3Q:6(a,b){K c="",d=a.1e("\\n").L,h=2u(J.V("2i-1s")),g=J.V("2z-1s-2t");I(g==R)g=(h+d-1).1q().L;Y I(3R(g)==R)g=0;O(K i=0;i\'+j+"17>":"")+i)}H a},4f:6(a){H a?"<4a>"+a+"4a>":""},4b:6(a,b){6 c(l){H(l=l?l.1V||g:g)?l+" ":""}O(K d=0,h="",g=J.V("1D",""),i=0;i|&1y;2R\\s*\\/?&1G;/2T;I(e.13.46==R)b=b.Q(h,"\\n");I(e.13.44==R)b=b.Q(h,"");b=b.1e("\\n");h=/^\\s*/;g=4Q;O(K i=0;i0;i++){K k=b[i];I(x(k).L!=0){k=h.X(k);I(k==N){a=a;1N a}g=1Q.4q(k[0].L,g)}}I(g>0)O(i=0;i\'+(J.V("16")?e.16.1H(J):"")+\'<3Z 5z="0" 5H="0" 5J="0">\'+J.4f(J.V("1t"))+"<3T><3P>"+(1u?\'<2d 1g="1u">\'+J.3Q(a)+"2d>":"")+\'<2d 1g="17">\'+b+"2d>3P>3T>3Z>"},2F:6(a){I(a===N)a="";J.17=a;K b=J.3Y("T");b.3X=J.1H(a);J.V("16")&&w(p(b,".16"),"5c",e.16.2b);J.V("3V-17")&&w(p(b,".17"),"56",f);H b},2Q:6(a){J.1c=""+1Q.5d(1Q.5n()*5k).1q();e.1Y.2A[t(J.1c)]=J;J.1n=C(e.2v,a||{});I(J.V("2k")==R)J.1n.16=J.1n.1u=11},5j:6(a){a=a.Q(/^\\s+|\\s+$/g,"").Q(/\\s+/g,"|");H"\\\\b(?:"+a+")\\\\b"},5f:6(a){J.28={18:{1I:a.18,23:"1k"},1b:{1I:a.1b,23:"1k"},17:1f M("(?<18>"+a.18.1m+")(?<17>.*?)(?<1b>"+a.1b.1m+")","5o")}}};H e}();1j 2e!="1d"&&(2e.1v=1v);',62,441,'||||||function|||||||||||||||||||||||||||||||||||||return|if|this|var|length|XRegExp|null|for|index|replace|true||div|push|getParam|call|exec|else|prototype||false|lastIndex|config|arguments|RegExp|toolbar|code|left|captureNames|slice|right|id|undefined|split|new|class|addToken|indexOf|typeof|script|className|source|params|substr|apply|toString|String|line|title|gutter|SyntaxHighlighter|_xregexp|strings|lt|html|test|OUTSIDE_CLASS|match|brush|document|target|gt|getHtml|regex|global|join|style|highlight|break|concat|window|Math|isRegExp|throw|value|brushes|brushName|space|alert|vars|http|syntaxhighlighter|expandSource|size|css|case|font|Fa|name|htmlScript|dA|can|handler|gm|td|exports|color|in|href|first|discoveredBrushes|light|collapse|object|cache|getButtonHtml|trigger|pattern|getLineHtml|nbsp|numbers|parseInt|defaults|com|items|www|pad|highlighters|execute|focus|func|all|getDiv|parentNode|navigator|INSIDE_CLASS|regexList|hasFlag|Match|useScriptTags|hasNamedCapture|text|help|init|br|input|gi|Error|values|span|list|250|height|width|screen|top|500|tagName|findElements|getElementsByTagName|aboutDialog|_blank|appendChild|charAt|Array|copyAsGlobal|setFlag|highlighter_|string|attachEvent|nodeName|floor|backref|output|the|TypeError|sticky|Za|iterate|freezeTokens|scope|type|textarea|alexgorbatchev|version|margin|2010|005896|gs|regexLib|body|center|align|noBrush|require|childNodes|DTD|xhtml1|head|org|w3|url|preventDefault|container|tr|getLineNumbersHtml|isNaN|userAgent|tbody|isLineHighlighted|quick|void|innerHTML|create|table|links|auto|smart|tab|stripBrs|tabs|bloggerMode|collapsed|plain|getCodeLinesHtml|caption|getMatchesHtml|findMatches|figureOutLineNumbers|removeNestedMatches|getTitleHtml|brushNotHtmlScript|substring|createElement|Highlighter|load|HtmlScript|Brush|pre|expand|multiline|min|Can|ignoreCase|find|blur|extended|toLowerCase|aliases|addEventListener|innerText|textContent|wasn|select|createTextNode|removeChild|option|same|frame|xmlns|dtd|twice|1999|equiv|meta|htmlscript|transitional|1E3|expected|PUBLIC|DOCTYPE|on|W3C|XHTML|TR|EN|Transitional||configured|srcElement|Object|after|run|dblclick|matchChain|valueOf|constructor|default|switch|click|round|execAt|forHtmlScript|token|gimy|functions|getKeywords|1E6|escape|within|random|sgi|another|finally|supply|MSIE|ie|toUpperCase|catch|returnValue|definition|event|border|imsx|constructing|one|Infinity|from|when|Content|cellpadding|flags|cellspacing|try|xhtml|Type|spaces|2930402|hosted_button_id|lastIndexOf|donate|active|development|keep|to|xclick|_s|Xml|please|like|you|paypal|cgi|cmd|webscr|bin|highlighted|scrollbars|aspScriptTags|phpScriptTags|sort|max|scriptScriptTags|toolbar_item|_|command|command_|number|getElementById|doubleQuotedString|singleLinePerlComments|singleLineCComments|multiLineCComments|singleQuotedString|multiLineDoubleQuotedString|xmlComments|alt|multiLineSingleQuotedString|If|https|1em|000|fff|background|5em|xx|bottom|75em|Gorbatchev|large|serif|CDATA|continue|utf|charset|content|About|family|sans|Helvetica|Arial|Geneva|3em|nogutter|Copyright|syntax|close|write|2004|Alex|open|JavaScript|highlighter|July|02|replaceChild|offset|83'.split('|'),0,{}))
================================================
FILE: compass-style.org/assets/javascripts/site.js
================================================
function changeTheme(theme, setCookie) {
el = $('html');
if (!theme) theme = el.hasClass('dark') ? 'light': 'dark';
else if (el.hasClass(theme)) return;
el.removeClass('light');
el.removeClass('dark');
el.addClass(theme);
setThemePreference(theme);
}
function changeSyntax(style, setCookie){
el = $('html');
el.removeClass('scss'); el.removeClass('sass');
el.addClass(style);
setStyleSyntaxPreference(style);
}
function changeExampleStyleSyntax(style, setCookie){
el = $('html');
el.removeClass('scss'); el.removeClass('sass'); el.removeClass('css');
el.addClass(style);
setExampleStyleSyntaxPreference(style);
}
function changeExampleMarkupSyntax(markup){
el = $('html');
el.removeClass('haml'); el.removeClass('html');
el.addClass(markup);
setExampleMarkupSyntaxPreference(markup);
}
function setThemePreference(theme) {
$.cookie("compass-theme", null);
$.cookie("compass-theme", theme, {
expires: 60 * 60 * 24 * 365 * 10,
path: '/'
});
}
function getThemePreference(defaultTheme) {
theme = $.cookie("compass-theme");
if (theme) {
changeTheme(theme, false);
} else {
changeTheme(defaultTheme, true);
}
}
function setStyleSyntaxPreference (mainSyntax) {
$.cookie("compass-syntax", null);
$.cookie("compass-syntax", mainSyntax, { expires: 60 * 60 * 24 * 365 * 10, path: '/' });
}
function setExampleStyleSyntaxPreference (exampleStyle) {
$.cookie("compass-example-style", null);
$.cookie("compass-example-style", exampleStyle, { expires: 60 * 60 * 24 * 365 * 10, path: '/' });
}
function setExampleMarkupSyntaxPreference (exampleMarkup) {
$.cookie("compass-example-markup", null);
$.cookie("compass-example-markup", exampleMarkup, { expires: 60 * 60 * 24 * 365 * 10, path: '/' });
}
function getSyntaxPreference(defaultSyntax, defaultMarkup) {
mainSyntaxCookie = $.cookie("compass-syntax");
mainSyntax = (mainSyntaxCookie) ? mainSyntaxCookie : defaultSyntax;
changeSyntax(mainSyntax);
// add example styling preferences
if ($('body').hasClass('demo')){
markupCookie = $.cookie("compass-example-markup");
styleCookie = $.cookie("compass-example-style");
markup = (markupCookie) ? markupCookie : defaultMarkup;
style = (styleCookie) ? styleCookie : defaultSyntax;
changeExampleStyleSyntax(style)
changeExampleMarkupSyntax(markup);
}
}
getThemePreference('dark');
$('document').ready(function(){
getSyntaxPreference('scss', 'html');
$('#page').click(function(event){
var target = $(event.target);
// Set Main Syntax Preference
if (target.parent().is('#syntax_pref')) {
changeSyntax(target.attr("rel"), true);
event.preventDefault();
// Set Demo page syntax preferences
} else if (target.parent().is('.syntax_pref')) {
event.preventDefault();
if (target.parent().parent().is('#markup')) {
changeExampleMarkupSyntax(target.attr("rel"), true);
} else {
changeExampleStyleSyntax(target.attr("rel"), true);
}
// Set Theme preference
} else if (target.is('#theme_pref') || target.parent().is('#theme_pref')) {
changeTheme();
event.preventDefault();
// View source for mixins & functions
} else if (target.attr("rel") == "view source") {
$(target.attr("href")).toggle();
event.preventDefault();
}
});
});
================================================
FILE: compass-style.org/authors.yml
================================================
chris:
fullname: Chris Eppstein
byline_link: http://chriseppstein.github.com/
brandon:
fullname: Brandon Mathis
eric:
fullname: Eric M. Suzanne
byline_link: http://ericsuzanne.com/
nico:
fullname: Nico Hagenburger
scott:
fullname: Scott Davis
================================================
FILE: compass-style.org/config.yaml
================================================
base_url: http://compass-style.org
text_extensions: [ 'css', 'erb', 'haml', 'htm', 'html', 'js', 'less', 'markdown', 'md', 'php', 'rb', 'sass', 'scss', 'txt', 'xml' ]
output_dir: output
data_sources:
-
type: filesystem_unified
items_root: /
layouts_root: /
-
type: filesystem_assets
items_root: /assets
layouts_root: /assets
watcher:
dirs_to_watch: ['content', 'layouts', 'lib', 'assets']
files_to_watch: ['config.yaml', 'Rules']
notify_on_compilation_success: true
notify_on_compilation_failure: true
================================================
FILE: compass-style.org/content/.livereload
================================================
# Lines starting with pound sign (#) are ignored.
# additional extensions to monitor
#config.exts << 'haml'
# exclude files with NAMES matching this mask
#config.exclusions << '~*'
# exclude files with PATHS matching this mask (if the mask contains a slash)
#config.exclusions << '/excluded_dir/*'
# exclude files with PATHS matching this REGEXP
#config.exclusions << /somedir.*(ab){2,4}.(css|js)$/
# reload the whole page when .js changes
#config.apply_js_live = false
# reload the whole page when .css changes
#config.apply_css_live = false
# wait 100ms for more changes before reloading a page
#config.grace_period = 0.1
================================================
FILE: compass-style.org/content/CHANGELOG.markdown
================================================
---
title: Compass History
crumb: CHANGELOG
body_id: changelog
layout: default
---
COMPASS CHANGELOG
=================
Upgrading compass is pretty easy.
Don't let all these details [scare you...](http://compass-style.org/help/tutorials/upgrading/im-scared/)
The Documentation for the [latest stable release](http://compass-style.org/docs/):
The Documentation for the [latest preview release](http://beta.compass-style.org/)
Every release contains updated caniuse data unless otherwise noted.
1.0.2 (UNRELEASED)
------------------
* Handle change in Sass 3.4.2 that requires importer paths to exist.
1.0.1 (08/19/2014)
------------------
* Add support for `woff2` font format.
* Handle gradient functions when not using the compass mixins.
1.0.0 (08/15/2014)
------------------
* `md5sum($file)` - new helper to compute the md5sum of a file. Can be
used to create sass-based asset-cache-buster implementations.
* Fixed a bug in compass watch that caused the watcher to abort when a
syntax error occured.
* Fix the broken `compass stats` command.
* Brought back support for the original webkit gradient syntax.
1.0.0.rc.1 (08/04/2014)
-----------------------
* Non-partials found in additional import paths specified in compass config are no longer compiled
to a subdirectory. (Issue #1737)
* Add vendor prefixes for repeating gradients. (Issue #401)
* The configuration adapters for compass configuration to Sass engine
options were moved to compass-core. (Issue #1739)
* Handle sprite images with uppercase characters. (Issue #1740)
* Sprite changes are not logged in quiet mode. (Issue #862)
* Fix import-once issue with sprites. (Issue #1720)
* Miscellaneous bug fixes.
1.0.0.rc.0 (08/01/2014)
-----------------------
* The compass watcher and compiler are now built upon the Sass watcher
and compiler, reducing the overal complexity and amount of code that's
needed to be maintained.
* The `--dry-run` option is no longer supported for any compass commands.
* Sass 3.4 is now supported.
* Numerous bug fixes to gradients. All current syntax is fully supported
and shimmed with older spec versions/vendor variants/svg when possible.
1.0.0.alpha.21 (07/16/2013)
---------------------------
* Handle the brightness() CSS syntax, which had been broken when compass
defined a function by the same name.
* Fixed incompatibilities between sass-globbing and import-once.
* [Numerous bug fixes](https://github.com/Compass/compass/compare/core-1.0.0.alpha.20...core-1.0.0.alpha.21)
1.0.0.alpha.20 (06/27/2013)
---------------------------
* [Numerous bug fixes](https://github.com/Compass/compass/compare/core-1.0.0.alpha.19...core-1.0.0.alpha.20)
1.0.0.alpha.19 (03/12/2103)
---------------------------
* The `rem()` mixin can now handle comma-separated and nested lists
for the `$values` argument, e.g. `rem(background-size, (2rem, 100% 24px, auto))`.
1.0.0.alpha.17 (12/20/2013)
---------------------------
* A variable `$compass-extensions` is available after importing
`compass/support` that is a map of extensions to their version.
* Fixed bugs in the `browser-out-of-scope` function.
* Update to the latest caniuse.com data.
* Url methods will now correctly handle urls with query strings in them.
* There are now ruby callbacks for when sourcemap files are saved.
* calc() expressions are now handled in gradients.
* Fix a bug in `compass --time` when writing sourcemaps.
* Sourcemap filenames now match the convention used in Sass
(`.css.map`) because chrome seems to require this.
* Compass frameworks can tell compass their version using the `:version`
option when registering themselves via `Compass::Frameworks.register`.
When loading an extension from rubygems, compass will automatically
detect the gem version in use.
1.0.0.alpha.16 (12/05/2013)
---------------------------
* Compass now depends the `compass-import-once` gem that implements an
import once behavior for the `@import` directive in Sass. This makes
`@import` behave how most people expect it to work. New projects will
automatically be set up to use this gem. Existing projects need to add
`require 'compass/import-once/activate'` to their configuration. More
details about the import once gem are available in the
[README](https://github.com/chriseppstein/compass/blob/master/import-once/README.md)
* Compass now supports Sass sourcemaps. Pass the `--sourcemap` option to
the compile or watch commands or set `sourcemap = true` in your
compass configuration.
0.13.alpha.8 (10/21/2013)
-------------------------
### Deprecations & Breaking changes
* **Breaking Change**: The CSS3PIE module has been removed.
* The experimental and legacy support configuration variables have been
removed. Vendor prefixing is now configured according to minimum
browser versions and browser usage statistic thresholds. [More
details](/help/documentation/tuning-vendor-prefixes/).
* The old box module has been deprecated. Please use the new flexbox module.
* The transform-legacy module which was deprecated in 0.12 has been removed.
* The blueprint framework has been removed from compass. The
docs are now at [compass-blueprint.org](http://compass-blueprint.org)
and the code is maintained as [its own
project](https://github.com/Compass/compass-blueprint) by [Stephen
Way](https://github.com/stephenway). Full details can be [found on the
blog](/blog/2012/05/20/removing-blueprint/).
* *alpha users only:* The input-placeholder mixin API has changed. It no longer accepts an argument.
* *alpha users only:* The selection mixin API has changed. It no longer accepts a selector as an argument.
* *alpha users only:* The flexbox module was completely rewritten.
[Documentation](/reference/compass/css3/flexbox/)
### Changes
* [CORE] Updated listen version
* [HELPERS] The `elements-of-type($type)` helper now accepts a type of `text-input`.
* [HELPERS] The `current-date()` and `current-time()` functions now have
reasonable default formats.
* [HELPERS] The `current-source-file()` helper now returns the top-level sass
file that is being compiled instead of the file you're currently in
and the path is relative to your Sass directory unless you specify it
should be an absolute path.
* [HELPERS] The `current-output-file()` helper now returns a path
relative to the css output directory unless you specify that it should
return an absolute path.
* [SPRITES] added :focus support for magic selectors
* [SPRITES] You can now set `$default-sprite-separator` or `$","2":"Only supports the [2012 syntax](http://www.w3.org/TR/2012/WD-css3-flexbox-20120322/)","3":"Does not support flex-wrap or flex-flow properties"},"usage_perc_y":68.36,"usage_perc_a":14.29,"ucprefix":false,"parent":"","keywords":"flex"},"webgl":{"title":"WebGL - 3D Canvas graphics","description":"Method of generating dynamic 3D graphics using JavaScript, accelerated through hardware","spec":"https://www.khronos.org/registry/webgl/specs/1.0/","status":"other","links":[{"url":"http://iewebgl.com/","title":"Polyfill for IE"},{"url":"http://www.khronos.org/webgl/wiki/Tutorial","title":"Tutorial"},{"url":"http://webkit.org/blog/603/webgl-now-available-in-webkit-nightlies/","title":"Webkit blog post"},{"url":"http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation","title":"Instructions on enabling WebGL"},{"url":"http://hacks.mozilla.org/2009/12/webgl-draft-released-today/","title":"Firefox blog post"}],"categories":["Canvas"],"stats":{"ie":{"5.5":"n","6":"p","7":"p","8":"p","9":"p","10":"p","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"a","5":"a","6":"a","7":"a","8":"a","9":"a","10":"a","11":"a","12":"a","13":"a","14":"a","15":"a","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"a","24":"a","25":"a","26":"a","27":"a","28":"a","29":"a","30":"a","31":"a","32":"a","33":"a","34":"a"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"a","9":"a","10":"a","11":"a","12":"a","13":"a","14":"a","15":"a","16":"a","17":"a","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"a","6":"a","6.1":"a","7":"a","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"a","12.1":"a","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"a","12.1":"a","22":"y"},"and_chr":{"36":"a"},"and_ff":{"31":"a"},"ie_mob":{"10":"p"}},"notes":"Support listed as \"partial\" refers to the fact that not all users with these browsers have WebGL access. This is due to the additional requirement for users to have [up to date video drivers](http://www.khronos.org/webgl/wiki/BlacklistsAndWhitelists). This problem was [solved in Chrome](http://blog.chromium.org/2012/02/gpu-accelerating-2d-canvas-and-enabling.html) as of version 18.\r\n\r\nNote that WebGL is part of the [Khronos Group](http://www.khronos.org/webgl/), not the W3C.","notes_by_num":{},"usage_perc_y":41.84,"usage_perc_a":23.44,"ucprefix":false,"parent":"canvas","keywords":"web gl"},"fileapi":{"title":"File API","description":"Method of manipulating file objects in web applications client-side, as well as programmatically selecting them and accessing their data.","spec":"http://www.w3.org/TR/FileAPI/","status":"wd","links":[{"url":"https://developer.mozilla.org/en/Using_files_from_web_applications","title":"MDN article"},{"url":"http://docs.webplatform.org/wiki/apis/file","title":"WebPlatform Docs"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"a","7":"a","8":"a","9":"a","10":"a","11":"a","12":"a","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"a","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"a","4":"a","4.1":"a","4.2-4.3":"a","4.4":"y","4.4.3":"y"},"bb":{"7":"a","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"Partial support in older Safari and other WebKit browsers refers to lacking FileReader support. ","notes_by_num":{},"usage_perc_y":74.57,"usage_perc_a":5.95,"ucprefix":false,"parent":"","keywords":"FileReader"},"shadowdom":{"title":"Shadow DOM","description":"Method of establishing and maintaining functional boundaries between DOM trees and how these trees interact with each other within a document, thus enabling better functional encapsulation within the DOM.","spec":"http://www.w3.org/TR/shadow-dom/","status":"wd","links":[{"url":"http://www.html5rocks.com/tutorials/webcomponents/shadowdom/","title":"HTML5Rocks - Shadow DOM 101 article"},{"url":"http://html5-demos.appspot.com/static/shadowdom-visualizer/index.html","title":"Shadow DOM Visualizer"}],"categories":["HTML5","DOM"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y x","4.4.3":"y x"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":40.43,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"web components"},"websockets":{"title":"Web Sockets","description":"Bidirectional communication technology for web apps","spec":"http://www.w3.org/TR/websockets/","status":"cr","links":[{"url":"http://docs.webplatform.org/wiki/apis/websocket","title":"WebPlatform Docs"},{"url":"http://websocket.org/aboutwebsocket.html","title":"WebSockets information"},{"url":"http://updates.html5rocks.com/2011/08/What-s-different-in-the-new-WebSocket-protocol","title":"Details on newer protocol"},{"url":"https://raw.github.com/phiggins42/has.js/master/detect/features.js#native-websockets","title":"has.js test"},{"url":"http://en.wikipedia.org/wiki/WebSocket","title":"Wikipedia"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"a","5":"a","6":"y x","7":"y x","8":"y x","9":"y x","10":"y x","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"a","5":"a","6":"a","7":"a","8":"a","9":"a","10":"a","11":"a","12":"a","13":"a","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"a","5.1":"a","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"a","11.1":"a","11.5":"a","11.6":"a","12":"a","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"a","5.0-5.1":"a","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"n","11":"a","11.1":"a","11.5":"a","12":"a","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"Partial support refers to the websockets implementation using an older version of the protocol and/or the implementation being disabled by default (due to security issues with the older protocol).","notes_by_num":{},"usage_perc_y":74.78,"usage_perc_a":1.56,"ucprefix":true,"parent":"","keywords":""},"script-async":{"title":"async attribute for external scripts","description":"The boolean async attribute on script elements allows the external JavaScript file to run when it's available, without delaying page load first.","spec":"http://www.w3.org/TR/html5/scripting-1.html#attr-script-async","status":"cr","links":[{"url":"http://ie.microsoft.com/testdrive/Performance/AsyncScripts/Default.html","title":"Demo"},{"url":"https://developer.mozilla.org/en/HTML/Element/script#Attributes","title":"MDN article"},{"url":"https://raw.github.com/phiggins42/has.js/master/detect/script.js#script-async","title":"has.js test"}],"categories":["DOM","HTML5"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"a","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"Using script.async = false; to maintain execution order for dynamically-added scripts isn't supported in Safari 5.0","notes_by_num":{},"usage_perc_y":80.62,"usage_perc_a":0.19,"ucprefix":false,"parent":"","keywords":""},"cors":{"title":"Cross-Origin Resource Sharing","description":"Method of performing XMLHttpRequests across domains","spec":"http://www.w3.org/TR/cors/","status":"rec","links":[{"url":"http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/","title":"Mozilla Hacks blog post"},{"url":"http://msdn.microsoft.com/en-us/library/cc288060(VS.85).aspx","title":"Alternative implementation by IE8"},{"url":"https://raw.github.com/phiggins42/has.js/master/detect/features.js#native-cors-xhr","title":"has.js test"},{"url":"http://dev.opera.com/articles/view/dom-access-control-using-cross-origin-resource-sharing/","title":"DOM access using CORS"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"a","9":"a","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"y","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"y","4.0-4.1":"y","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"y","2.2":"y","2.3":"y","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"Supported somewhat in IE8 and IE9 using the XDomainRequest object (but has [limitations]( http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx))","notes_by_num":{},"usage_perc_y":82.6,"usage_perc_a":7.06,"ucprefix":false,"parent":"","keywords":""},"calc":{"title":"calc() as CSS unit value","description":"Method of allowing calculated values for length units, i.e. width: calc(100% - 3em)","spec":"http://www.w3.org/TR/css3-values/#calc","status":"cr","links":[{"url":"http://docs.webplatform.org/wiki/css/functions/calc","title":"WebPlatform Docs"},{"url":"https://developer.mozilla.org/en/CSS/-moz-calc","title":"MDN article"},{"url":"http://hacks.mozilla.org/2010/06/css3-calc/","title":"Mozilla Hacks article"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"a","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"y x","5":"y x","6":"y x","7":"y x","8":"y x","9":"y x","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"y x","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"y x","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"y x"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"Support can be somewhat emulated in older versions of IE using the non-standard expression() syntax. Partial support in IE9 refers to the browser crashing when used as a background-position value.","notes_by_num":{"0":""},"usage_perc_y":74.17,"usage_perc_a":2.6,"ucprefix":false,"parent":"","keywords":""},"ruby":{"title":"Ruby annotation","description":"Method of adding pronunciation or other annotations using ruby elements (primarily used in East Asian typography)","spec":"http://www.w3.org/TR/html-markup/ruby.html","status":"wd","links":[{"url":"http://html5doctor.com/ruby-rt-rp-element/","title":"HTML5 Doctor article"},{"url":"http://docs.webplatform.org/wiki/html/elements/ruby","title":"WebPlatform Docs"},{"url":"https://addons.mozilla.org/firefox/addon/1935/","title":"Add-on \"XHTML Ruby Support\" for Firefox"},{"url":"https://addons.mozilla.org/firefox/addon/6812/","title":"Addon \"HTML Ruby\" for Firefox support"}],"categories":["HTML5"],"stats":{"ie":{"5.5":"a","6":"a","7":"a","8":"a","9":"a","10":"a","11":"a"},"firefox":{"2":"p","3":"p","3.5":"p","3.6":"p","4":"p","5":"p","6":"p","7":"p","8":"p","9":"p","10":"p","11":"p","12":"p","13":"p","14":"p","15":"p","16":"p","17":"p","18":"p","19":"p","20":"p","21":"p","22":"p","23":"p","24":"p","25":"p","26":"p","27":"p","28":"p","29":"p","30":"p","31":"p","32":"p","33":"p","34":"p"},"chrome":{"4":"p","5":"a","6":"a","7":"a","8":"a","9":"a","10":"a","11":"a","12":"a","13":"a","14":"a","15":"a","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"a","24":"a","25":"a","26":"a","27":"a","28":"a","29":"a","30":"a","31":"a","32":"a","33":"a","34":"a","35":"a","36":"a","37":"a","38":"a","39":"a"},"safari":{"3.1":"p","3.2":"p","4":"p","5":"a","5.1":"a","6":"a","6.1":"a","7":"a","8":"a"},"opera":{"9":"p","9.5-9.6":"p","10.0-10.1":"p","10.5":"p","10.6":"p","11":"p","11.1":"p","11.5":"p","11.6":"p","12":"p","12.1":"p","15":"a","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"a","24":"a"},"ios_saf":{"3.2":"p","4.0-4.1":"p","4.2-4.3":"p","5.0-5.1":"a","6.0-6.1":"a","7.0-7.1":"a","8":"a"},"op_mini":{"5.0-7.0":"p"},"android":{"2.1":"p","2.2":"p","2.3":"p","3":"a","4":"a","4.1":"a","4.2-4.3":"a","4.4":"a","4.4.3":"a"},"bb":{"7":"p","10":"a"},"op_mob":{"10":"p","11":"p","11.1":"p","11.5":"p","12":"p","12.1":"p","22":"a"},"and_chr":{"36":"a"},"and_ff":{"31":"p"},"ie_mob":{"10":"a"}},"notes":"Browsers without native support can still simulate support using CSS. Partial support refers to only supporting basic ruby, may still be missing writing-mode, Complex ruby and CSS3 Ruby","notes_by_num":{},"usage_perc_y":0,"usage_perc_a":74.18,"ucprefix":false,"parent":"","keywords":""},"css-opacity":{"title":"CSS3 Opacity","description":"Method of setting the transparency level of an element","spec":"http://www.w3.org/TR/css3-color/","status":"rec","links":[{"url":"http://www.css3files.com/color/#opacity","title":"Information page"},{"url":"http://docs.webplatform.org/wiki/css/properties/opacity","title":"WebPlatform Docs"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"a","6":"a","7":"a","8":"a","9":"y","10":"y","11":"y"},"firefox":{"2":"y","3":"y","3.5":"y","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"y","3.2":"y","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"y","9.5-9.6":"y","10.0-10.1":"y","10.5":"y","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"y","4.0-4.1":"y","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"y"},"android":{"2.1":"y","2.2":"y","2.3":"y","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"y","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"Transparency for elements in IE8 and older can be achieved using the proprietary \"filter\" property and does not work well with PNG images using alpha transparency.","notes_by_num":{},"usage_perc_y":88.57,"usage_perc_a":4.89,"ucprefix":false,"parent":"","keywords":"transparent,transparency,alpha"},"form-validation":{"title":"Form validation","description":"Method of setting required fields and field types without requiring JavaScript","spec":"http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#client-side-form-validation","status":"wd","links":[{"url":"http://docs.webplatform.org/wiki/html/attributes/required","title":"WebPlatform Docs"}],"categories":["HTML5"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"a","5.1":"a","6":"a","6.1":"a","7":"a","8":"a"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"y","10.5":"y","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"y"},"bb":{"7":"n","10":"y"},"op_mob":{"10":"y","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"a"}},"notes":"Partial support in Safari refers to lack of notice when form with required fields is attempted to be submitted. Partial support in IE10 mobile refers to lack of warning when blocking submission.","notes_by_num":{},"usage_perc_y":64.74,"usage_perc_a":3.81,"ucprefix":false,"parent":"forms","keywords":""},"history":{"title":"Session history management","description":"Method of manipulating the user's browser's session history in JavaScript using history.pushState, history.replaceState and the popstate event","spec":"http://www.w3.org/TR/html5/browsers.html#history-1","status":"cr","links":[{"url":"https://raw.github.com/phiggins42/has.js/master/detect/features.js#native-history-state","title":"has.js test"},{"url":"http://docs.webplatform.org/wiki/dom/History","title":"WebPlatform Docs"},{"url":"http://html5demos.com/history","title":"Demo page"},{"url":"http://www.adequatelygood.com/2010/7/Saner-HTML5-History-Management","title":"Introduction to history management"},{"url":"https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history","title":"MDN article"},{"url":"https://github.com/browserstate/history.js","title":"History.js polyfill "}],"categories":["HTML5"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"a","5.1":"a","6":"a","6.1":"a","7":"a","8":"a"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"a","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"y","2.3":"y","3":"n","4":"n","4.1":"n","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"Older iOS versions and Android 4.0.4 claim support, but implementation is too buggy to be useful. Partial support in other Safari browsers refers to other buggy behavior.","notes_by_num":{},"usage_perc_y":75.98,"usage_perc_a":3.44,"ucprefix":false,"parent":"","keywords":"onpushstate,onreplacestate"},"json":{"title":"JSON parsing","description":"Method of converting JavaScript objects to JSON strings and JSON back to objects using JSON.stringify() and JSON.parse()","spec":"http://es5.github.com/#x15.12","status":"other","links":[{"url":"http://docs.webplatform.org/wiki/apis/json","title":"WebPlatform Docs"},{"url":"https://developer.mozilla.org/En/Using_native_JSON","title":"MDN article"},{"url":"https://raw.github.com/phiggins42/has.js/master/detect/json.js#json","title":"has.js test"},{"url":"http://www.json.org/js.html","title":"JSON in JS (includes script w/support)"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"y","9":"y","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"y","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"y","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"y","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"y"},"android":{"2.1":"y","2.2":"y","2.3":"y","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"y","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"Requires document to be in IE8+ [standards mode](http://msdn.microsoft.com/en-us/library/cc288325(VS.85).aspx) to work in IE8.","notes_by_num":{},"usage_perc_y":92.91,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":""},"classlist":{"title":"classList (DOMTokenList )","description":"Method of easily manipulating classes on elements, using the DOMTokenList object.","spec":"http://www.w3.org/TR/dom/#dom-element-classlist","status":"wd","links":[{"url":"http://www.sitepoint.com/exploring-classlist-api/","title":"SitePoint article"},{"url":"http://aurelio.audero.it/demo/classlist-api-demo.html","title":"Demo using classList"},{"url":"http://hacks.mozilla.org/2010/01/classlist-in-firefox-3-6/","title":"Mozilla Hacks article"},{"url":"http://docs.webplatform.org/wiki/dom/Element/classList","title":"WebPlatform Docs"},{"url":"https://github.com/eligrey/classList.js","title":"Polyfill script"}],"categories":["HTML5","DOM"],"stats":{"ie":{"5.5":"p","6":"p","7":"p","8":"p","9":"p","10":"y","11":"y"},"firefox":{"2":"p","3":"p","3.5":"p","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"p","5":"p","6":"p","7":"p","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"p","3.2":"p","4":"p","5":"p","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"p","9.5-9.6":"p","10.0-10.1":"p","10.5":"p","10.6":"p","11":"p","11.1":"p","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"p","4.0-4.1":"p","4.2-4.3":"p","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"p"},"android":{"2.1":"p","2.2":"p","2.3":"p","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"p","11":"p","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":81.07,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":""},"text-overflow":{"title":"CSS3 Text-overflow","description":"Append ellipsis when text overflows its containing element","spec":"http://www.w3.org/TR/css3-ui/#text-overflow0","status":"wd","links":[{"url":"https://raw.github.com/phiggins42/has.js/master/detect/css.js#css-text-overflow","title":"has.js test"},{"url":"https://github.com/rmorse/AutoEllipsis","title":"jQuery polyfill for Firefox"},{"url":"http://www.css3files.com/text/","title":"Information page"},{"url":"https://developer.mozilla.org/En/CSS/Text-overflow","title":"MDN article"},{"url":"http://docs.webplatform.org/wiki/css/properties/text-overflow","title":"WebPlatform Docs"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"n","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y"},"firefox":{"2":"p","3":"p","3.5":"p","3.6":"p","4":"p","5":"p","6":"p","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"y","3.2":"y","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"y x","9.5-9.6":"y x","10.0-10.1":"y x","10.5":"y x","10.6":"y x","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"y","4.0-4.1":"y","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"y x"},"android":{"2.1":"y","2.2":"y","2.3":"y","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"y x","11":"y x","11.1":"y x","11.5":"y x","12":"y x","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":93.11,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"textoverflow,ellipsis"},"webm":{"title":"WebM video format","description":"Multimedia format designed to provide a royalty-free, high-quality open video compression format for use with HTML5 video. WebM supports the video codec VP8 and VP9.","spec":"http://www.webmproject.org/","status":"other","links":[{"url":"http://perian.org/","title":"Perian :Mac OSX Webm Codec install"},{"url":"https://tools.google.com/dlpage/webmmf","title":"Codec for IE9 support"},{"url":"http://webmproject.org","title":"Official website"},{"url":"https://raw.github.com/phiggins42/has.js/master/detect/video.js#video-webm","title":"has.js test"},{"url":"http://www.broken-links.com/2010/09/01/playing-webm-in-safari-with-plugins/","title":"Info on supporting WebM in Safari"}],"categories":["Other"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"p","10":"p","11":"p"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"a","5":"a","6":"a","7":"a","8":"a","9":"a","10":"a","11":"a","12":"a","13":"a","14":"a","15":"a","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"a","24":"a","25":"a","26":"a","27":"a","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"a","7":"a","8":"a","9":"a","10":"a","11":"a","12":"a","13":"a","14":"a","15":"a","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"a","24":"a","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"p","4":"p","5":"p","5.1":"p","6":"p","6.1":"p","7":"p","8":"p"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"a","11":"a","11.1":"a","11.5":"a","11.6":"a","12":"a","12.1":"a","15":"a","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"a","3":"a","4":"a","4.1":"a","4.2-4.3":"a","4.4":"a","4.4.3":"a"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"a"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"p"}},"notes":"Will work in IE9+ and Safari/MacOSX provided the user has the WebM codecs installed. Partial support indicates that at least one codec is supported but not all.","notes_by_num":{},"usage_perc_y":51.32,"usage_perc_a":10.47,"ucprefix":false,"parent":"video","keywords":"matroska"},"mpeg4":{"title":"MPEG-4/H.264 video format","description":"Commonly used video compression format (not royalty-free)","spec":"http://ip.hhi.de/imagecom_G1/assets/pdfs/csvt_overview_0305.pdf","status":"other","links":[{"url":"http://www.interoperabilitybridges.com/html5-extension-for-wmp-plugin","title":"Firefox extension allowing support in Win7"},{"url":"http://en.wikipedia.org/wiki/H.264/MPEG-4_AVC","title":"Wikipedia article"}],"categories":["Other"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"y","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"a","22":"a","23":"a","24":"a","25":"a","26":"a","27":"a","28":"a","29":"a","30":"a","31":"a","32":"a","33":"a","34":"a"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"y","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"y","4.0-4.1":"y","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"a","2.2":"a","2.3":"a","3":"a","4":"a","4.1":"a","4.2-4.3":"a","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"n","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"a"},"ie_mob":{"10":"y"}},"notes":"The Android 2.3 browser currently requires [specific handling](http://www.broken-links.com/2010/07/08/making-html5-video-work-on-android-phones/) to play videos. Firefox [will include support](http://blog.lizardwrangler.com/2012/03/18/video-user-experience-and-our-mission/) on some platforms in upcoming versions. Firefox supports H.264 on Windows 7 and later since version 21. Firefox supports H.264 on Linux since version 26 if the appropriate gstreamer plug-ins are installed. Partial support for Firefox refers to the lack of support in OSX & some Linux platforms, for Android Firefox it refers to the inability of hardware acceleration.","notes_by_num":{},"usage_perc_y":64.15,"usage_perc_a":18.98,"ucprefix":false,"parent":"video","keywords":"avc,mp4,mpv,mov,aac"},"ogv":{"title":"Ogg/Theora video format","description":"Free lossy video compression format.","spec":"http://theora.org/doc/","status":"other","links":[{"url":"http://en.wikipedia.org/wiki/Theora","title":"Wikipedia article"}],"categories":["Other"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"p","10":"p","11":"p"},"firefox":{"2":"n","3":"n","3.5":"y","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"y","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"y"},"ie_mob":{"10":"p"}},"notes":"","notes_by_num":{},"usage_perc_y":49.58,"usage_perc_a":0,"ucprefix":false,"parent":"video","keywords":"xiph"},"wordwrap":{"title":"CSS3 Overflow-wrap","description":"Allows lines to be broken within words if an otherwise unbreakable string is too long to fit.","spec":"http://www.w3.org/TR/css3-text/#overflow-wrap","status":"wd","links":[{"url":"http://www.css3files.com/text/#wordwrap","title":"Information page"},{"url":"http://docs.webplatform.org/wiki/css/properties/word-wrap","title":"WebPlatform Docs"},{"url":"https://developer.mozilla.org/En/CSS/Word-wrap","title":"MDN article"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"a","6":"a","7":"a","8":"a","9":"a","10":"a","11":"a"},"firefox":{"2":"n","3":"n","3.5":"a","3.6":"a","4":"a","5":"a","6":"a","7":"a","8":"a","9":"a","10":"a","11":"a","12":"a","13":"a","14":"a","15":"a","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"a","24":"a","25":"a","26":"a","27":"a","28":"a","29":"a","30":"a","31":"a","32":"a","33":"a","34":"a"},"chrome":{"4":"a","5":"a","6":"a","7":"a","8":"a","9":"a","10":"a","11":"a","12":"a","13":"a","14":"a","15":"a","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"a","3.2":"a","4":"a","5":"a","5.1":"a","6":"a","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"a","10.6":"a","11":"a","11.1":"a","11.5":"a","11.6":"a","12":"a","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"a","4.0-4.1":"a","4.2-4.3":"a","5.0-5.1":"a","6.0-6.1":"a","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"a"},"android":{"2.1":"a","2.2":"a","2.3":"a","3":"a","4":"a","4.1":"a","4.2-4.3":"a","4.4":"y","4.4.3":"y"},"bb":{"7":"a","10":"y"},"op_mob":{"10":"a","11":"a","11.1":"a","11.5":"a","12":"a","12.1":"a","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"a"},"ie_mob":{"10":"a"}},"notes":"Partial support refers to requiring the legacy name \"word-wrap\" (rather than overflow-wrap) to work.","notes_by_num":{},"usage_perc_y":48.74,"usage_perc_a":44.61,"ucprefix":false,"parent":"","keywords":"wordwrap,word-wrap"},"progressmeter":{"title":"Progress & Meter","description":"Method of indicating a progress state (progress element) or the current level of a gauge (meter element).\r\n","spec":"http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#the-progress-element","status":"wd","links":[{"url":"http://dev.opera.com/articles/view/new-form-features-in-HTML5/#newoutput","title":"Dev.Opera article"},{"url":"http://docs.webplatform.org/wiki/html/elements/progress","title":"WebPlatform Docs"},{"url":"http://peter.sh/examples/?/html/meter-progress.html","title":"Examples of progress and meter elements"},{"url":"http://html5doctor.com/measure-up-with-the-meter-tag/","title":"HTML5 Doctor on meter element "}],"categories":["HTML5"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"a","11":"a"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"a","7":"a","8":"a","9":"a","10":"a","11":"a","12":"a","13":"a","14":"a","15":"a","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"a","8":"a"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"n","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"a"}},"notes":"Partial support in Firefox 6-15, IE10 & iOS7 Safari refers to supporting the progress element, but not the meter element. iOS7 Safari also does not support \"indeterminate\" progress elements.","notes_by_num":{},"usage_perc_y":57.92,"usage_perc_a":16.47,"ucprefix":false,"parent":"forms","keywords":""},"object-fit":{"title":"CSS3 object-fit/object-position","description":"Method of specifying how an object (image or video) should fit inside its box. object-fit options include \"contain\" (fit according to aspect ratio), \"fill\" (stretches object to fill) and \"cover\" (overflows box but maintains ratio), where object-position allows the object to be repositioned like background-image does.","spec":"http://www.w3.org/TR/css3-images/","status":"cr","links":[{"url":"https://github.com/anselmh/object-fit","title":"object-fit JavaScript-Polyfill"},{"url":"http://dev.opera.com/articles/view/css3-object-fit-object-position/","title":"Dev.Opera article"},{"url":"http://docs.webplatform.org/wiki/css/properties/object-fit","title":"WebPlatform Docs"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"u","33":"u","34":"u"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"y x","11":"y x","11.1":"y x","11.5":"y x","11.6":"y x","12":"y x","12.1":"y x","15":"n","16":"n","17":"n","18":"n","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"y x","11.1":"y x","11.5":"y x","12":"y x","12.1":"y x","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":38.46,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"objectfit,objectposition"},"xhr2":{"title":"XMLHttpRequest 2","description":"Adds more functionality to AJAX requests like file uploads, transfer progress information and the ability to send form data.","spec":"http://www.w3.org/TR/XMLHttpRequest2/","status":"wd","links":[{"url":"http://docs.webplatform.org/wiki/apis/xhr/XMLHttpRequest","title":"WebPlatform Docs"},{"url":"https://developer.mozilla.org/en/XMLHttpRequest/FormData","title":"MDN article on FormData"},{"url":"https://github.com/3nr1c/jUri.js","title":"Polyfill for FormData object"}],"categories":["DOM","JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"a","3.6":"a","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"u","5":"u","6":"u","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":81.11,"usage_perc_a":0.16,"ucprefix":false,"parent":"","keywords":"formdata"},"minmaxwh":{"title":"CSS min/max-width/height","description":"Method of setting a minimum or maximum width or height to an element. ","spec":"http://www.w3.org/TR/CSS21/visudet.html#min-max-widths","status":"rec","links":[{"url":"http://www.impressivewebs.com/min-max-width-height-css/","title":"CSS Basics post"},{"url":"http://docs.webplatform.org/wiki/css/properties/min-width","title":"WebPlatform Docs"},{"url":"http://code.google.com/p/ie7-js/","title":"JS library with support"}],"categories":["CSS2"],"stats":{"ie":{"5.5":"p","6":"p","7":"y","8":"y","9":"y","10":"y","11":"y"},"firefox":{"2":"y","3":"y","3.5":"y","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"y","3.2":"y","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"y","9.5-9.6":"y","10.0-10.1":"y","10.5":"y","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"y","4.0-4.1":"y","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"y"},"android":{"2.1":"y","2.2":"y","2.3":"y","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"y","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"IE7 does not support \"inherit\" as a value on any of these properties. IE8 has some bugs with max-width/height combined with overflow: auto/scroll.","notes_by_num":{},"usage_perc_y":93.17,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"min-width,min-height,max-width,max-height"},"details":{"title":"Details & Summary elements","description":"The <details> element generates a simple no-JavaScript widget to show/hide element contents, optionally by clicking on its child <summary> element.","spec":"http://www.whatwg.org/specs/web-apps/current-work/multipage/interactive-elements.html#the-details-element","status":"wd","links":[{"url":"http://mathiasbynens.be/notes/html5-details-jquery","title":"jQuery fallback script"},{"url":"https://raw.github.com/phiggins42/has.js/master/detect/features.js#native-details","title":"has.js test"},{"url":"http://docs.webplatform.org/wiki/html/elements/details","title":"WebPlatform Docs"},{"url":"http://html5doctor.com/summary-figcaption-element/","title":"HTML5 Doctor article"},{"url":"https://gist.github.com/370590","title":"Fallback script"}],"categories":["HTML5"],"stats":{"ie":{"5.5":"n","6":"p","7":"p","8":"p","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"p","3.5":"p","3.6":"p","4":"p","5":"p","6":"p","7":"p","8":"p","9":"p","10":"p","11":"p","12":"p","13":"p","14":"p","15":"p","16":"p","17":"p","18":"p","19":"p","20":"p","21":"p","22":"p","23":"p","24":"p","25":"p","26":"p","27":"p","28":"p","29":"p","30":"p","31":"p","32":"p","33":"p","34":"p"},"chrome":{"4":"p","5":"p","6":"p","7":"p","8":"p","9":"p","10":"p","11":"p","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"p","3.2":"p","4":"p","5":"p","5.1":"p","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"p","9.5-9.6":"p","10.0-10.1":"p","10.5":"p","10.6":"p","11":"p","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"p","4.0-4.1":"p","4.2-4.3":"p","5.0-5.1":"p","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"p"},"android":{"2.1":"p","2.2":"p","2.3":"p","3":"p","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"p","10":"y"},"op_mob":{"10":"p","11":"p","11.1":"p","11.5":"p","12":"p","12.1":"p","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":55.2,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":""},"text-stroke":{"title":"CSS text-stroke","description":"Method of declaring the outline (stroke) width and color for text.","spec":"http://developer.apple.com/library/safari/documentation/appleapplications/reference/SafariCSSRef/Articles/StandardCSSProperties.html#//apple_ref/doc/uid/TP30001266-_webkit_text_stroke","status":"unoff","links":[{"url":"http://www.westciv.com/tools/textStroke/","title":"Live editor"},{"url":"http://css-tricks.com/7405-adding-stroke-to-web-text/","title":"Information & workarounds"}],"categories":["CSS"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"u","33":"u","34":"u"},"chrome":{"4":"y x","5":"y x","6":"y x","7":"y x","8":"y x","9":"y x","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x","35":"y x","36":"y x","37":"y x","38":"y x","39":"y x"},"safari":{"3.1":"y x","3.2":"y x","4":"y x","5":"y x","5.1":"y x","6":"y x","6.1":"y x","7":"y x","8":"y x"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x"},"ios_saf":{"3.2":"a x","4.0-4.1":"y x","4.2-4.3":"y x","5.0-5.1":"y x","6.0-6.1":"y x","7.0-7.1":"y x","8":"y x"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"y x","2.2":"y x","2.3":"y x","3":"n","4":"y x","4.1":"y x","4.2-4.3":"y x","4.4":"y x","4.4.3":"y x"},"bb":{"7":"y x","10":"y x"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y x"},"and_chr":{"36":"y x"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"Does not yet appear in any W3C specification. Was briefly included in a spec as the \"text-outline\" property, but this was removed.","notes_by_num":{},"usage_perc_y":57.88,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"textstroke,stroke-color,stroke-width,fill-color"},"inline-block":{"title":"CSS inline-block","description":"Method of displaying an element as a block while flowing it with text. ","spec":"http://www.w3.org/TR/CSS21/visuren.html#fixed-positioning","status":"rec","links":[{"url":"http://docs.webplatform.org/wiki/css/properties/display","title":"WebPlatform Docs"},{"url":"http://robertnyman.com/2010/02/24/css-display-inline-block-why-it-rocks-and-why-it-sucks/","title":"Blog post w/info"},{"url":"http://blog.mozilla.com/webdev/2009/02/20/cross-browser-inline-block/","title":"Info on cross browser support"}],"categories":["CSS2"],"stats":{"ie":{"5.5":"a","6":"a","7":"a","8":"y","9":"y","10":"y","11":"y"},"firefox":{"2":"a x","3":"y","3.5":"y","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"y","3.2":"y","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"y","9.5-9.6":"y","10.0-10.1":"y","10.5":"y","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"y","4.0-4.1":"y","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"y"},"android":{"2.1":"y","2.2":"y","2.3":"y","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"y","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"Only supported in IE6 and IE7 on elements with a display of \"inline\" by default. [Alternative properties](http://blog.mozilla.com/webdev/2009/02/20/cross-browser-inline-block/) are available to provide complete cross-browser support.","notes_by_num":{},"usage_perc_y":93.03,"usage_perc_a":0.43,"ucprefix":false,"parent":"","keywords":"inlineblock"},"notifications":{"title":"Web Notifications","description":"Method of alerting the user outside of a web page by displaying notifications (that do not require interaction by the user).","spec":"http://www.w3.org/TR/notifications/","status":"wd","links":[{"url":"http://www.chromium.org/developers/design-documents/desktop-notifications/api-specification","title":"Chromium API"},{"url":"http://www.html5rocks.com/tutorials/notifications/quick/","title":"HTML5 Rocks tutorial"},{"url":"http://aurelio.audero.it/demo/web-notifications-api-demo.html","title":"Demo"},{"url":"https://addons.mozilla.org/en-us/firefox/addon/221523/","title":"Add-on "},{"url":"https://developer.mozilla.org/en-US/docs/Web/API/notification","title":"MDN Notifications"},{"url":"http://www.sitepoint.com/introduction-web-notifications-api/","title":"SitePoint article"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"a x","6":"a x","7":"a x","8":"a x","9":"a x","10":"a x","11":"a x","12":"a x","13":"a x","14":"a x","15":"a x","16":"a x","17":"a x","18":"a x","19":"a x","20":"a x","21":"a x","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"a x","4.4.3":"a x"},"bb":{"7":"n","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"a x"},"and_chr":{"36":"n"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":48.79,"usage_perc_a":1.85,"ucprefix":false,"parent":"","keywords":""},"stream":{"title":"getUserMedia/Stream API","description":"Method of accessing external device data (such as a webcam video stream). Formerly this was envisioned as the <device> element.","spec":"http://www.w3.org/TR/mediacapture-streams/","status":"wd","links":[{"url":"http://docs.webplatform.org/wiki/dom/Navigator/getUserMedia","title":"WebPlatform Docs"},{"url":"http://my.opera.com/core/blog/2011/03/23/webcam-orientation-preview","title":"Technology preview from Opera"}],"categories":["JS API","HTML5"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x","35":"y x","36":"y x","37":"y x","38":"y x","39":"y x"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"y","12.1":"y","15":"n","16":"n","17":"n","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"y x"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"y","12.1":"y","22":"y x"},"and_chr":{"36":"y"},"and_ff":{"31":"y x"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":53.69,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"camera,device,getUserMedia,media stream,Media Capture API"},"svg-img":{"title":"SVG in HTML img element","description":"Method of displaying SVG images in HTML using <img>","spec":"http://www.w3.org/TR/html5/dom.html#embedded-content","status":"cr","links":[{"url":"http://blog.dholbert.org/2010/10/svg-as-image.html","title":"Blog post with examples"},{"url":"http://www.codedread.com/blog/","title":"Blog with SVGs an images"}],"categories":["SVG"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"y","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"a","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"y","9.5-9.6":"y","10.0-10.1":"y","10.5":"y","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"a","4.0-4.1":"y","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"y"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"y","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":87.2,"usage_perc_a":0.01,"ucprefix":false,"parent":"","keywords":"svg-as-img,svg-in-img"},"datalist":{"title":"Datalist element","description":"Method of setting a list of options for a user to select in a text field, while leaving the ability to enter a custom value.","spec":"http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#the-datalist-element","status":"wd","links":[{"url":"http://github.com/thgreasi/datalist-polyfill","title":"Minimal Datalist polyfill w/tutorial"},{"url":"https://developer.mozilla.org/en/HTML/Element/datalist","title":"MDN reference"},{"url":"http://hacks.mozilla.org/2010/11/firefox-4-html5-forms/","title":"Mozilla Hacks article"},{"url":"http://docs.webplatform.org/wiki/html/elements/datalist","title":"WebPlatform Docs"},{"url":"http://demo.agektmr.com/datalist/","title":"Eiji Kitamura's options demos & tests"},{"url":"http://afarkas.github.com/webshim/demos/","title":"HTML5 Library including datalist support"}],"categories":["HTML5"],"stats":{"ie":{"5.5":"n","6":"p","7":"p","8":"p","9":"p","10":"a","11":"a"},"firefox":{"2":"p","3":"p","3.5":"p","3.6":"p","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"p","5":"p","6":"p","7":"p","8":"p","9":"p","10":"p","11":"p","12":"p","13":"p","14":"p","15":"p","16":"p","17":"p","18":"p","19":"n","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"p","3.2":"p","4":"p","5":"p","5.1":"p","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"y","9.5-9.6":"y","10.0-10.1":"y","10.5":"y","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"p","4.0-4.1":"p","4.2-4.3":"p","5.0-5.1":"p","6.0-6.1":"p","7.0-7.1":"p","8":"p"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"p","2.2":"p","2.3":"p","3":"p","4":"p","4.1":"p","4.2-4.3":"p","4.4":"p","4.4.3":"y"},"bb":{"7":"p","10":"y"},"op_mob":{"10":"y","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"p"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"p"}},"notes":"Partial support in IE10 refers to [significantly buggy behavior](http://playground.onereason.eu/2013/04/ie10s-lousy-support-for-datalists/).","notes_by_num":{},"usage_perc_y":54.54,"usage_perc_a":9.81,"ucprefix":false,"parent":"forms","keywords":"list attribute"},"dataset":{"title":"dataset & data-* attributes","description":"Method of applying and accessing custom data to elements.","spec":"http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#embedding-custom-non-visible-data-with-the-data-*-attributes","status":"wd","links":[{"url":"http://html5doctor.com/html5-custom-data-attributes/","title":"HTML5 Doctor article"},{"url":"http://html5demos.com/dataset","title":"Demo using dataset"},{"url":"https://raw.github.com/phiggins42/has.js/master/detect/dom.js#dom-dataset","title":"has.js test"},{"url":"https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes","title":"MDN Guide - Using data-* attributes"},{"url":"http://docs.webplatform.org/wiki/html/attributes/data-*","title":"WebPlatform Docs"},{"url":"https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement.dataset","title":"MDN Reference - dataset"}],"categories":["HTML5"],"stats":{"ie":{"5.5":"a","6":"a","7":"a","8":"a","9":"a","10":"a","11":"y"},"firefox":{"2":"a","3":"a","3.5":"a","3.6":"a","4":"a","5":"a","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"a","5":"a","6":"a","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"a","3.2":"a","4":"a","5":"a","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"a","9.5-9.6":"a","10.0-10.1":"a","10.5":"a","10.6":"a","11":"a","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"a","4.0-4.1":"a","4.2-4.3":"a","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"a"},"android":{"2.1":"a","2.2":"a","2.3":"a","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"a","11":"a","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"a"}},"notes":"All browsers can already use data-* attributes and access them using getAttribute. \"Supported\" refers to accessing the values using the dataset property. Current spec only refers to support on HTML elements, only some browsers also have support for SVG/MathML elements.","notes_by_num":{},"usage_perc_y":77.85,"usage_perc_a":15.61,"ucprefix":false,"parent":"","keywords":"DOMStringMap"},"css-grid":{"title":"CSS Grid Layout","description":"Method of using a grid concept to lay out content, providing a mechanism for authors to divide available space for lay out into columns and rows using a set of predictable sizing behaviors","spec":"http://www.w3.org/TR/css3-grid-layout/","status":"wd","links":[{"url":"https://bugs.webkit.org/show_bug.cgi?id=60731","title":"Webkit (Chrome, Safari, etc.) feature request"},{"url":"https://bugzilla.mozilla.org/show_bug.cgi?id=616605","title":"Mozilla (Firefox) feature request"},{"url":"http://blogs.msdn.com/b/ie/archive/2011/04/14/ie10-platform-preview-and-css-features-for-adaptive-layouts.aspx","title":"IE Blog post"},{"url":"https://github.com/codler/Grid-Layout-Polyfill","title":"Grid Layout Polyfill"}],"categories":["CSS"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"p","10":"y x","11":"y x"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"p","20":"p","21":"p","22":"p","23":"p","24":"p","25":"p","26":"p","27":"p","28":"p","29":"p","30":"p","31":"p","32":"u","33":"u","34":"u"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"p","26":"p","27":"p","28":"p","29":"p","30":"p","31":"p","32":"p","33":"p","34":"p","35":"p","36":"p","37":"u","38":"u","39":"u"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"p","6.1":"p","7":"p","8":"p"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"p","7.0-7.1":"p","8":"p"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"p","4.4":"p","4.4.3":"p"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"p"},"and_chr":{"36":"p"},"and_ff":{"31":"n"},"ie_mob":{"10":"y x"}},"notes":"","notes_by_num":{},"usage_perc_y":10.22,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"grids,grid-row,grid-column"},"menu":{"title":"Toolbar/context menu","description":"Method of defining a toolbar menu, a context menu or a list of (interactive) options using the <menu> element.","spec":"http://www.whatwg.org/specs/web-apps/current-work/multipage/interactive-elements.html#the-menuitem-element","status":"cr","links":[{"url":"http://addyosmani.github.com/jQuery-contextMenu/","title":"jQuery polyfill"},{"url":"https://bug617528.bugzilla.mozilla.org/attachment.cgi?id=554309","title":"Demo"},{"url":"https://raw.github.com/phiggins42/has.js/master/detect/events.js#event-contextmenu","title":"has.js test"}],"categories":["HTML5"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"a","9":"a","10":"a","11":"a","12":"a","13":"a","14":"a","15":"a","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"a","24":"a","25":"a","26":"a","27":"a","28":"a","29":"a","30":"a","31":"a","32":"a","33":"a","34":"a"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n","35":"n","36":"n","37":"u","38":"u","39":"u"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"Partial support in Firefox refers to being limited to context menus, not toolbar menus.","notes_by_num":{},"usage_perc_y":0,"usage_perc_a":13.68,"ucprefix":false,"parent":"","keywords":"contextmenu,menuitem,command"},"rem":{"title":"rem (root em) units","description":"Type of unit similar to \"em\", but relative only to the root element, not any parent element. Thus compounding does not occur as it does with \"em\" units.","spec":"http://www.w3.org/TR/css3-values/#font-relative-lengths","status":"cr","links":[{"url":"http://snook.ca/archives/html_and_css/font-size-with-rem","title":"Article on usage"},{"url":"https://github.com/chuckcarpenter/REM-unit-polyfill","title":"REM Polyfill"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"y","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"u","5":"u","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"y","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"y","2.2":"y","2.3":"y","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":85.05,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"rems"},"ttf":{"title":"TTF/OTF - TrueType and OpenType font support","description":"Support for the TrueType (.ttf)and OpenType (.otf) outline font formats in @font-face. ","spec":"http://developer.apple.com/fonts/TTRefMan/index.html","status":"other","links":[{"url":"http://stackoverflow.com/questions/17694143/what-is-the-status-of-ttf-support-in-internet-explorer","title":"What is the status of TTF support in Internet Explorer?"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"a","10":"a","11":"a"},"firefox":{"2":"n","3":"n","3.5":"y","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"y","3.2":"y","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"y","10.5":"y","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"y","2.3":"y","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"y","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"u"}},"notes":"Partial support in IE9 refers to the fonts only working [when set to be \"installable\"](http://blogs.msdn.com/b/ie/archive/2010/07/15/the-css-corner-better-web-typography-for-better-design.aspx).","notes_by_num":{},"usage_perc_y":72.43,"usage_perc_a":12.41,"ucprefix":false,"parent":"fontface","keywords":""},"touch":{"title":"Touch events","description":"Method of registering when, where and how the interface is touched, for devices with a touch screen. These DOM events are similar to mousedown, mousemove, etc.","spec":"http://www.w3.org/TR/touch-events/","status":"rec","links":[{"url":"http://www.quirksmode.org/m/tests/drag2.html","title":"Multi-touch demo"},{"url":"http://msdn.microsoft.com/en-us/library/ie/hh673557(v=vs.85).aspx","title":"Internet Explorer's gesture and touch implementation."},{"url":"http://github.com/CamHenlin/TouchPolyfill","title":"Touch polyfill for supporting touch events on Internet Explorer"},{"url":"http://schepers.cc/getintouch","title":"Information on the spec development"},{"url":"http://www.quirksmode.org/mobile/tableTouch.html","title":"Detailed support tables"}],"categories":["DOM","JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"p","11":"p"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"a","5":"a","6":"a","7":"a","8":"a","9":"a","10":"a","11":"a","12":"a","13":"a","14":"a","15":"a","16":"a","17":"a","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"y","4.0-4.1":"y","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"y","2.2":"y","2.3":"y","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"n","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"p"}},"notes":"Internet Explorer implements Pointer Events specification which supports more input devices than Touch Events one.\r\n\r\nRemoved support in Firefox refers to desktop Firefox only.","notes_by_num":{},"usage_perc_y":54.45,"usage_perc_a":0.79,"ucprefix":false,"parent":"","keywords":"touchstart,touchend,touchmove,touchenter,touchleave,touchcancel"},"matchesselector":{"title":"matches() DOM method","description":"Method of testing whether or not a DOM element matches a given selector. Formerly known (and largely supported with prefix) as matchesSelector.","spec":"http://www.w3.org/TR/selectors-api2/","status":"wd","links":[{"url":"http://docs.webplatform.org/wiki/dom/HTMLElement/matchesSelector","title":"WebPlatform Docs"},{"url":"https://developer.mozilla.org/en/DOM/Element.mozMatchesSelector","title":"MDN article"}],"categories":["DOM","JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"a x","10":"a x","11":"a x"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"a x","4":"a x","5":"a x","6":"a x","7":"a x","8":"a x","9":"a x","10":"a x","11":"a x","12":"a x","13":"a x","14":"a x","15":"a x","16":"a x","17":"a x","18":"a x","19":"a x","20":"a x","21":"a x","22":"a x","23":"a x","24":"a x","25":"a x","26":"a x","27":"a x","28":"a x","29":"a x","30":"a x","31":"a x","32":"a x","33":"a x","34":"a x"},"chrome":{"4":"a x","5":"a x","6":"a x","7":"a x","8":"a x","9":"a x","10":"a x","11":"a x","12":"a x","13":"a x","14":"a x","15":"a x","16":"a x","17":"a x","18":"a x","19":"a x","20":"a x","21":"a x","22":"a x","23":"a x","24":"a x","25":"a x","26":"a x","27":"a x","28":"a x","29":"a x","30":"a x","31":"a x","32":"a x","33":"a x","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"a x","5.1":"a x","6":"a x","6.1":"a x","7":"a x","8":"a x"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"a x","11.6":"a x","12":"a x","12.1":"a x","15":"a x","16":"a x","17":"a x","18":"a x","19":"a x","20":"a x","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"a x","4.2-4.3":"a x","5.0-5.1":"a x","6.0-6.1":"a x","7.0-7.1":"a x","8":"a x"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"a x","2.3":"a x","3":"a x","4":"a x","4.1":"a x","4.2-4.3":"a x","4.4":"a x","4.4.3":"a x"},"bb":{"7":"a x","10":"a x"},"op_mob":{"10":"n","11":"n","11.1":"a x","11.5":"a x","12":"a x","12.1":"a x","22":"a x"},"and_chr":{"36":"y"},"and_ff":{"31":"a x"},"ie_mob":{"10":"a x"}},"notes":"Partial support refers to supporting the older specification's \"matchesSelector\" name rather than just \"matches\".","notes_by_num":{},"usage_perc_y":36,"usage_perc_a":49.08,"ucprefix":false,"parent":"","keywords":" matchesSelector"},"pointer-events":{"title":"CSS pointer-events (for HTML)","description":"This CSS property, when set to \"none\" allows elements to not receive hover/click events, instead the event will occur on anything behind it. ","spec":"http://wiki.csswg.org/spec/css4-ui#pointer-events","status":"unoff","links":[{"url":"http://robertnyman.com/2010/03/22/css-pointer-events-to-allow-clicks-on-underlying-elements/","title":"Article & tutorial"},{"url":"https://raw.github.com/phiggins42/has.js/master/detect/css.js#css-pointerevents","title":"has.js test"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"y","4.0-4.1":"y","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"y","2.2":"y","2.3":"y","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"Already part of the SVG specification, and all SVG-supporting browsers appear to support the property on SVG elements.","notes_by_num":{},"usage_perc_y":79.12,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"pointerevents"},"blobbuilder":{"title":"Blob constructing","description":"Construct Blobs (binary large objects) either using the BlobBuilder API (deprecated) or the Blob constructor.","spec":"http://www.w3.org/TR/file-writer-api/#the-blobbuilder-interface","status":"wd","links":[{"url":"https://developer.mozilla.org/en/DOM/BlobBuilder","title":"MDN article on BlobBuilder"},{"url":"https://developer.mozilla.org/en-US/docs/DOM/Blob","title":"MDN article on Blobs"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"a x","7":"a x","8":"a x","9":"a x","10":"a x","11":"a x","12":"a x","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"a x","9":"a x","10":"a x","11":"a x","12":"a x","13":"a x","14":"a x","15":"a x","16":"a x","17":"a x","18":"a x","19":"a x","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"a x","4":"a x","4.1":"a x","4.2-4.3":"a x","4.4":"a x","4.4.3":"a x"},"bb":{"7":"n","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"Partial support refers to only supporting the now deprecated BlobBuilder to create blobs.","notes_by_num":{},"usage_perc_y":73.15,"usage_perc_a":6.68,"ucprefix":true,"parent":"fileapi","keywords":""},"filereader":{"title":"FileReader API","description":"Method of reading the contents of a File or Blob object into memory","spec":"http://www.w3.org/TR/FileAPI/#dfn-filereader","status":"wd","links":[{"url":"http://docs.webplatform.org/wiki/apis/file/FileReader","title":"WebPlatform Docs"},{"url":"https://developer.mozilla.org/en/DOM/FileReader","title":"FileReader API"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":80.14,"usage_perc_a":0,"ucprefix":false,"parent":"fileapi","keywords":""},"filesystem":{"title":"Filesystem & FileWriter API","description":"Method of reading and writing files to a sandboxed file system.","spec":"http://www.w3.org/TR/file-system-api/","status":"unoff","links":[{"url":"http://www.html5rocks.com/en/tutorials/file/filesystem/","title":"HTML5 Rocks tutorial"},{"url":"http://docs.webplatform.org/wiki/apis/filesystem","title":"WebPlatform Docs"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"a x","9":"a x","10":"a x","11":"a x","12":"a x","13":"y x","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x","35":"y x","36":"y x","37":"y x","38":"y x","39":"y x"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"y x"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y x"},"and_chr":{"36":"y x"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"The File API: Directories and System specification is no longer being maintained and support may be dropped in future versions.","notes_by_num":{},"usage_perc_y":40.33,"usage_perc_a":0.21,"ucprefix":false,"parent":"","keywords":"filewriter"},"bloburls":{"title":"Blob URLs","description":"Method of creating URL handles to the specified File or Blob object.","spec":"http://www.w3.org/TR/FileAPI/#url","status":"wd","links":[{"url":"https://developer.mozilla.org/en/DOM/window.URL.createObjectURL","title":"MDN article"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"y x","9":"y x","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"y x","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"y x","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"y x","4.1":"y x","4.2-4.3":"y x","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"y x"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y x"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":79.1,"usage_perc_a":0,"ucprefix":false,"parent":"fileapi","keywords":"createobjecturl"},"rellist":{"title":"relList (DOMTokenList)","description":"Method of easily manipulating rel attribute values on elements, using the DOMTokenList object (similar to classList).","spec":"http://www.w3.org/TR/html5/text-level-semantics.html#the-a-element","status":"wd","links":[{"url":"https://developer.mozilla.org/en-US/docs/DOM/DOMTokenList","title":"MDN - DOMTokenList"}],"categories":["HTML5","DOM"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n","35":"n","36":"n","37":"n","38":"n","39":"n"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":5.02,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":""},"typedarrays":{"title":"Typed Arrays","description":"JavaScript typed arrays provide a mechanism for accessing raw binary data much more efficiently.\r\n","spec":"http://www.khronos.org/registry/typedarray/specs/latest/","status":"other","links":[{"url":"https://developer.mozilla.org/en/javascript_typed_arrays","title":"MDN article"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":80.86,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"float64array,dataview,uint8array"},"deviceorientation":{"title":"DeviceOrientation events","description":"API for detecting orientation and motion events from the device running the browser.","spec":"http://www.w3.org/TR/orientation-event/","status":"wd","links":[{"url":"http://html5labs.interoperabilitybridges.com/prototypes/device-orientation-events/device-orientation-events/info","title":"DeviceOrientation implementation prototype for IE10"},{"url":"http://www.html5rocks.com/en/tutorials/device/orientation/","title":"HTML5 Rocks tutorial"},{"url":"http://aurelio.audero.it/demo/device-orientation-api-demo.html","title":"Demo"},{"url":"https://raw.github.com/phiggins42/has.js/master/detect/features.js#native-orientation","title":"has.js test"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"a"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"p","4":"p","5":"p","6":"a","7":"a","8":"a","9":"a","10":"a","11":"a","12":"a","13":"a","14":"a","15":"a","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"a","24":"a","25":"a","26":"a","27":"a","28":"a","29":"a","30":"a","31":"a","32":"a","33":"a","34":"a"},"chrome":{"4":"n","5":"n","6":"n","7":"a","8":"a","9":"a","10":"a","11":"a","12":"a","13":"a","14":"a","15":"a","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"a","24":"a","25":"a","26":"a","27":"a","28":"a","29":"a","30":"a","31":"a","32":"a","33":"a","34":"a","35":"a","36":"a","37":"a","38":"a","39":"a"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"a","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"a","24":"a"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"a","5.0-5.1":"a","6.0-6.1":"a","7.0-7.1":"a","8":"a"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"a","4":"a","4.1":"a","4.2-4.3":"a","4.4":"a","4.4.3":"a"},"bb":{"7":"n","10":"a"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"y","12.1":"y","22":"a"},"and_chr":{"36":"a"},"and_ff":{"31":"a"},"ie_mob":{"10":"n"}},"notes":"Partial support refers to the lack of compassneedscalibration event. Partial support also refers to the lack of devicemotion event support for Chrome 30- and Opera. Opera Mobile 14 lost the ondevicemotion event support. Firefox 3.6, 4 and 5 support the non-standard [MozOrientation](https://developer.mozilla.org/en/DOM/MozOrientation) event.","notes_by_num":{},"usage_perc_y":0.08,"usage_perc_a":74.12,"ucprefix":false,"parent":"","keywords":""},"script-defer":{"title":"defer attribute for external scripts","description":"The boolean defer attribute on script elements allows the external JavaScript file to run when the DOM is loaded, without delaying page load first.","spec":"http://www.w3.org/TR/html5/the-script-element.html#attr-script-defer","status":"cr","links":[{"url":"https://developer.mozilla.org/en/HTML/Element/script#Attributes","title":"MDN article"},{"url":"http://docs.webplatform.org/wiki/html/attributes/defer","title":"WebPlatform Docs"},{"url":"https://raw.github.com/phiggins42/has.js/master/detect/script.js#script-defer","title":"has.js test"}],"categories":["DOM","HTML5"],"stats":{"ie":{"5.5":"a","6":"a","7":"a","8":"a","9":"a","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"y","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"Partial support refers to a buggy implementation in IE<10","notes_by_num":{},"usage_perc_y":80.84,"usage_perc_a":7.49,"ucprefix":false,"parent":"","keywords":""},"nav-timing":{"title":"Navigation Timing API","description":"API for accessing timing information related to navigation and elements.","spec":"http://www.w3.org/TR/navigation-timing/","status":"cr","links":[{"url":"http://www.html5rocks.com/en/tutorials/webperformance/basics/","title":"HTML5 Rocks tutorial"},{"url":"http://docs.webplatform.org/wiki/apis/navigation_timing","title":"WebPlatform Docs"},{"url":"https://developer.mozilla.org/en/API/navigationTiming","title":"MDN article"}],"categories":["JS API","DOM"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"y","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"y x","7":"y x","8":"y x","9":"y x","10":"y x","11":"y x","12":"y x","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":73.09,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"performance,performance.timing"},"audio-api":{"title":"Web Audio API","description":"High-level JavaScript API for processing and synthesizing audio","spec":"http://www.w3.org/TR/webaudio/","status":"wd","links":[{"url":"http://docs.webplatform.org/wiki/apis/webaudio","title":"WebPlatform Docs"},{"url":"http://www.doboism.com/projects/webaudio-compatibility/","title":"Additional browser compatibility tests for specific features"},{"url":"https://github.com/corbanbrook/audionode.js","title":"Polyfill to support Web Audio API in Firefox"},{"url":"https://github.com/g200kg/WAAPISim","title":"Polyfill to enable Web Audio API through Firefox Audio Data api or flash"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"y x","6.1":"y x","7":"y x","8":"y x"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"y x","7.0-7.1":"y x","8":"y x"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"Firefox versions < 25 support an alternative, deprecated audio API.","notes_by_num":{},"usage_perc_y":61.8,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"web-audio"},"css-regions":{"title":"CSS Regions","description":"Method of flowing content into multiple elements.","spec":"http://www.w3.org/TR/css3-regions/","status":"wd","links":[{"url":"http://html.adobe.com/webstandards/cssregions/","title":"Adobe demos and samples"},{"url":"http://msdn.microsoft.com/en-us/ie/hh272902#_CSSConnected","title":"IE10 developer guide info"},{"url":"http://docs.webplatform.org/wiki/css/atrules/@region","title":"WebPlatform Docs"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"a x","11":"a x"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"a x","16":"a x","17":"a x","18":"a x","19":"n d","20":"n d","21":"n d","22":"n d","23":"n d","24":"n d","25":"n d","26":"n d","27":"n d","28":"n d","29":"n d","30":"n d","31":"n d","32":"n d","33":"n d","34":"n d","35":"n","36":"n","37":"n","38":"n","39":"n"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"y x","7":"y x","8":"y x"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"y x","8":"y x"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"n"},"ie_mob":{"10":"a x"}},"notes":"Support in IE10 and IE11 is limited to using an iframe as a content source with the `-ms-flow-into: flow_name;` and `-ms-flow-from: flow_name;` syntax. ","notes_by_num":{},"usage_perc_y":7.91,"usage_perc_a":10.36,"ucprefix":false,"parent":"","keywords":""},"fullscreen":{"title":"Full Screen API","description":"API for allowing content (like a video or canvas element) to take up the entire screen.","spec":"http://www.w3.org/TR/fullscreen/","status":"wd","links":[{"url":"https://developer.mozilla.org/en/DOM/Using_full-screen_mode","title":"MDN article"},{"url":"http://docs.webplatform.org/wiki/dom/methods/requestFullscreen","title":"WebPlatform Docs"},{"url":"http://jlongster.com/2011/11/21/canvas.html","title":"Blog post"},{"url":"http://hacks.mozilla.org/2012/01/using-the-fullscreen-api-in-web-browsers/","title":"Mozilla hacks article"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"y x"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"a x","11":"a x","12":"a x","13":"a x","14":"a x","15":"a x","16":"a x","17":"a x","18":"a x","19":"a x","20":"a x","21":"a x","22":"a x","23":"a x","24":"a x","25":"a x","26":"a x","27":"a x","28":"a x","29":"a x","30":"a x","31":"a x","32":"a x","33":"a x","34":"a x"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"a x","16":"a x","17":"a x","18":"a x","19":"a x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x","35":"y x","36":"y x","37":"y x","38":"y x","39":"y x"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"a x","6":"y x","6.1":"y x","7":"y x","8":"y x"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"y","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"a"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y x"},"and_chr":{"36":"y x"},"and_ff":{"31":"a x"},"ie_mob":{"10":"n"}},"notes":"Partial support refers to supporting an earlier draft of the spec.","notes_by_num":{},"usage_perc_y":50.15,"usage_perc_a":14.55,"ucprefix":false,"parent":"","keywords":"full-screen"},"requestanimationframe":{"title":"requestAnimationFrame","description":"API allowing a more efficient way of running script-based animation, compared to traditional methods using timeouts.","spec":"http://www.w3.org/TR/animation-timing/#requestAnimationFrame","status":"cr","links":[{"url":"http://paulirish.com/2011/requestanimationframe-for-smart-animating/","title":"Blog post"},{"url":"http://hacks.mozilla.org/2011/08/animating-with-javascript-from-setinterval-to-requestanimationframe/","title":"Mozilla Hacks article"},{"url":"http://docs.webplatform.org/wiki/dom/Window/requestAnimationFrame","title":"WebPlatform Docs"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"y x","5":"y x","6":"y x","7":"y x","8":"y x","9":"y x","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"y x","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"y x","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"y x"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":74.57,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":""},"input-range":{"title":"Range input type","description":"Form field type that allows the user to select a value using a slider widget.","spec":"http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#range-state-(type=range)","status":"wd","links":[{"url":"http://docs.webplatform.org/wiki/html/elements/input/type/range","title":"WebPlatform Docs"},{"url":"https://github.com/andreruffert/rangeslider.js","title":"rangeslider.js polyfill"},{"url":"https://raw.github.com/phiggins42/has.js/master/detect/form.js#input-type-range","title":"has.js test"},{"url":"https://github.com/fryn/html5slider","title":"Polyfill for Firefox"},{"url":"https://github.com/freqdec/fd-slider","title":"Cross-browser polyfill"},{"url":"http://tutorialzine.com/2011/12/what-you-need-to-know-html5-range-input/","title":"Tutorial"}],"categories":["HTML5"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"u","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"y","3.2":"y","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"y","9.5-9.6":"y","10.0-10.1":"y","10.5":"y","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"a","2.2":"a","2.3":"a","3":"a","4":"a","4.1":"a","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"y","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"Currently all Android browsers with partial support hide the slider input field by default. However, the element [can be styled](http://tiffanybbrown.com/2012/02/07/input-typerange-and-androids-stock-browser/) to be made visible and usable.","notes_by_num":{},"usage_perc_y":77.16,"usage_perc_a":3.98,"ucprefix":false,"parent":"forms","keywords":""},"matchmedia":{"title":"matchMedia","description":"API for finding out whether or not a media query applies to the document.","spec":"http://www.w3.org/TR/cssom-view/#dom-window-matchmedia","status":"wd","links":[{"url":"http://docs.webplatform.org/wiki/css/media_queries/apis/matchMedia","title":"WebPlatform Docs"},{"url":"https://github.com/paulirish/matchMedia.js/","title":"matchMedia.js polyfill"},{"url":"https://developer.mozilla.org/en/CSS/Using_media_queries_from_code","title":"MDN tutorial"},{"url":"https://developer.mozilla.org/en/DOM/window.matchMedia","title":"MDN article"}],"categories":["JS API","DOM"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":80.68,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"mediaquerylist"},"input-datetime":{"title":"Date/time input types","description":"Form field widget to easily allow users to enter dates and/or times, generally by using a calendar widget.","spec":"http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#date-state-(type=date)","status":"wd","links":[{"url":"http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-cross-browser-datepickers-within-minutes/","title":"Datepicker tutorial w/polyfill"},{"url":"https://github.com/zoltan-dulac/html5Forms.js","title":"Polyfill for HTML5 forms"},{"url":"https://raw.github.com/phiggins42/has.js/master/detect/form.js#input-type-datetime;input-type-datetime-local","title":"has.js test"},{"url":"http://docs.webplatform.org/wiki/html/elements/input/type/date","title":"WebPlatform Docs"}],"categories":["HTML5"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"a","21":"a","22":"a","23":"a","24":"a","25":"a","26":"a","27":"a","28":"a","29":"a","30":"a","31":"a","32":"a","33":"a","34":"a","35":"a","36":"a","37":"a","38":"a","39":"a"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"u","7":"n","8":"n"},"opera":{"9":"y","9.5-9.6":"y","10.0-10.1":"y","10.5":"y","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"a","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"a","24":"a"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"a","6.0-6.1":"a","7.0-7.1":"a","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"y"},"op_mob":{"10":"y","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"a"},"and_chr":{"36":"y"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"Safari provides date-formatted text fields, but no real calendar widget. Partial support in Chrome refers to a missing calendar widget for the \"datetime\" type (and other types in older versions). Some modified versions of the Android 4.x browser do have support for date/time fields. Partial support in iOS refers to a lack of support for attributes like step, min, or max.","notes_by_num":{},"usage_perc_y":6.98,"usage_perc_a":41.2,"ucprefix":false,"parent":"forms","keywords":"datepicker,timepicker"},"input-color":{"title":"Color input type","description":"Form field allowing the user to select a color.","spec":"http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#color-state-(type=color)","status":"wd","links":[{"url":"http://docs.webplatform.org/wiki/html/elements/input/type/color","title":"WebPlatform Docs"},{"url":"https://github.com/jonstipe/color-polyfill","title":"Polyfill"},{"url":"http://www.html5tutorial.info/html5-color.php","title":"Tutorial"}],"categories":["HTML5"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"n","16":"n","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"y","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":53.17,"usage_perc_a":0,"ucprefix":false,"parent":"forms","keywords":"colour"},"input-number":{"title":"Number input type","description":"Form field type for numbers.","spec":"http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#number-state-(type=number)","status":"wd","links":[{"url":"http://docs.webplatform.org/wiki/html/elements/input/type/number","title":"WebPlatform Docs"},{"url":"https://github.com/jonstipe/number-polyfill","title":"Polyfill"},{"url":"http://www.html5tutorial.info/html5-number.php","title":"Tutorial"},{"url":"https://raw.github.com/phiggins42/has.js/master/detect/form.js#input-type-number","title":"has.js test"}],"categories":["HTML5"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"a","11":"a"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"y","9.5-9.6":"y","10.0-10.1":"y","10.5":"y","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"a","4.0-4.1":"a","4.2-4.3":"a","5.0-5.1":"a","6.0-6.1":"a","7.0-7.1":"a","8":"a"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"a","4.1":"a","4.2-4.3":"a","4.4":"a","4.4.3":"a"},"bb":{"7":"n","10":"a"},"op_mob":{"10":"y","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"a"},"and_chr":{"36":"a"},"and_ff":{"31":"a"},"ie_mob":{"10":"a"}},"notes":"iOS Safari, Android 4, Chrome for Android show number input, but do not use \"step\", \"min\" or \"max\" attributes or show increment/decrement buttons. Internet Explorer 10 and 11 do not show increment/decrement buttons.","notes_by_num":{},"usage_perc_y":50.41,"usage_perc_a":28.39,"ucprefix":false,"parent":"forms","keywords":"spinner"},"iframe-sandbox":{"title":"sandbox attribute for iframes","description":"Method of running external site pages with reduced privileges (e.g. no JavaScript) in iframes","spec":"http://www.w3.org/TR/html5/embedded-content-0.html#attr-iframe-sandbox","status":"cr","links":[{"url":"http://docs.webplatform.org/wiki/html/attributes/sandbox","title":"WebPlatform Docs"},{"url":"http://msdn.microsoft.com/en-us/hh563496","title":"MSDN article"},{"url":"http://blog.chromium.org/2010/05/security-in-depth-html5s-sandbox.html","title":"Chromium blog article"}],"categories":["HTML5"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"a","24":"a","25":"a","26":"a","27":"a","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"y","2.3":"y","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":79.82,"usage_perc_a":1.34,"ucprefix":false,"parent":"","keywords":""},"css-counters":{"title":"CSS Counters","description":"Method of controlling number values in generated content, using the counter-reset and counter-increment properties.","spec":"http://www.w3.org/TR/CSS21/generate.html#counters","status":"wd","links":[{"url":"http://onwebdev.blogspot.com/2012/02/css-counters-tutorial.html","title":"Tutorial and information"},{"url":"https://developer.mozilla.org/en/CSS_Counters","title":"MDN article"},{"url":"http://docs.webplatform.org/wiki/css/properties/counter-reset","title":"WebPlatform Docs"}],"categories":["CSS2"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"y","9":"y","10":"y","11":"y"},"firefox":{"2":"y","3":"y","3.5":"y","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"y","3.2":"y","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"y","9.5-9.6":"y","10.0-10.1":"y","10.5":"y","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"y","4.0-4.1":"y","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"y"},"android":{"2.1":"y","2.2":"y","2.3":"y","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"y","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":93.04,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":""},"css-resize":{"title":"CSS resize property","description":"Method of allowing an element to be resized by the user, with options to limit to a given direction. ","spec":"http://www.w3.org/TR/css3-ui/#resize","status":"wd","links":[{"url":"http://davidwalsh.name/textarea-resize","title":"On textarea resizing"},{"url":"http://css-tricks.com/almanac/properties/r/resize/","title":"CSS Tricks info"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"y x","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"a","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"Opera 12.10+ currently only supports the resize property for textarea elements.","notes_by_num":{},"usage_perc_y":58.05,"usage_perc_a":0.32,"ucprefix":false,"parent":"","keywords":"horizontal,vertical"},"input-placeholder":{"title":"input placeholder attribute","description":"Method of setting placeholder text for text-like input fields, to suggest the expected inserted information.","spec":"http://dev.w3.org/html5/spec/Overview.html#attr-input-placeholder","status":"cr","links":[{"url":"http://docs.webplatform.org/wiki/html/attributes/placeholder","title":"WebPlatform Docs"},{"url":"https://code.google.com/p/android/issues/detail?id=24626","title":"Issue 24626: Placeholder text for an input type="},{"url":"http://www.zachleat.com/web/placeholder/","title":"Article on usage"},{"url":"https://raw.github.com/phiggins42/has.js/master/detect/form.js#input-attr-placeholder","title":"has.js test"},{"url":"https://github.com/mathiasbynens/jquery-placeholder","title":"Polyfill"}],"categories":["HTML5"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"a","3.2":"a","4":"a","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"a","11.1":"a","11.5":"a","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"y","4.0-4.1":"y","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"y","2.2":"y","2.3":"y","3":"y","4":"a","4.1":"a","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"n","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"Partial support in older Safari and Opera versions refers to lacking placeholder support on textarea elements. ","notes_by_num":{},"usage_perc_y":79.47,"usage_perc_a":3.02,"ucprefix":false,"parent":"forms","keywords":""},"spdy":{"title":"SPDY networking protocol","description":"Networking protocol for low-latency transport of content over the web.","spec":"http://tools.ietf.org/html/draft-mbelshe-httpbis-spdy-00","status":"unoff","links":[{"url":"http://dev.chromium.org/spdy/spdy-whitepaper","title":"SPDY whitepaper"},{"url":"http://en.wikipedia.org/wiki/SPDY","title":"Wikipedia"}],"categories":["Other"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"a"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":60.33,"usage_perc_a":7.18,"ucprefix":false,"parent":"","keywords":""},"css-repeating-gradients":{"title":"CSS Repeating Gradients","description":"Method of defining a repeating linear or radial color gradient as a CSS image.","spec":"http://www.w3.org/TR/css3-images/#repeating-gradients","status":"cr","links":[{"url":"http://docs.webplatform.org/wiki/css/repeating-linear-gradient","title":"WebPlatform Docs"},{"url":"https://developer.mozilla.org/en/CSS/repeating-linear-gradient","title":"MDN article"},{"url":"http://www.css3files.com/gradient/#repeatinglineargradient","title":"Information page"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"y x","4":"y x","5":"y x","6":"y x","7":"y x","8":"y x","9":"y x","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"y x","6":"y x","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"a x","11.5":"a x","11.6":"y x","12":"y x","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"y x","6.0-6.1":"y x","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"y x","4.1":"y x","4.2-4.3":"y x","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"y x"},"op_mob":{"10":"n","11":"n","11.1":"a x","11.5":"a x","12":"y x","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"Firefox 10+, Chrome 26+ and Opera 11.6+ also support the new \"to (side)\" syntax.","notes_by_num":{},"usage_perc_y":80.92,"usage_perc_a":0.02,"ucprefix":false,"parent":"css-gradients","keywords":""},"css-filters":{"title":"CSS Filter Effects","description":"Method of applying filter effects (like blur, grayscale, brightness, contrast and hue) to elements, previously only possible by using SVG.","spec":"http://www.w3.org/TR/filter-effects/","status":"wd","links":[{"url":"http://dl.dropbox.com/u/3260327/angular/CSS3ImageManipulation.html","title":"Filter editor"},{"url":"http://html5-demos.appspot.com/static/css/filters/index.html","title":"Demo file for WebKit browsers"},{"url":"http://bennettfeely.com/filters/","title":"Filter Playground"},{"url":"http://www.html5rocks.com/en/tutorials/filters/understanding-css/","title":"HTML5Rocks article"}],"categories":["CSS3","CSS"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"a","4":"a","5":"a","6":"a","7":"a","8":"a","9":"a","10":"a","11":"a","12":"a","13":"a","14":"a","15":"a","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"a","24":"a","25":"a","26":"a","27":"a","28":"a","29":"a","30":"a","31":"a","32":"a","33":"a","34":"a"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x","35":"y x","36":"y x","37":"y x","38":"y x","39":"y x"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"y x","6.1":"y x","7":"y x","8":"y x"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"y x","7.0-7.1":"y x","8":"y x"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y x","4.4.3":"y x"},"bb":{"7":"n","10":"y x"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y x"},"and_chr":{"36":"y x"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"Note that this property is significantly different from and incompatible with Microsoft's [older \"filter\" property](http://msdn.microsoft.com/en-us/library/ie/ms530752%28v=vs.85%29.aspx).\r\n\r\nPartial support in Firefox 31 [only with url() version](https://developer.mozilla.org/en-US/docs/Web/CSS/filter#Browser_compatibility)","notes_by_num":{},"usage_perc_y":50.09,"usage_perc_a":13.94,"ucprefix":false,"parent":"","keywords":"sepia,hue-rotate,invert,saturate"},"getcomputedstyle":{"title":"getComputedStyle","description":"API to get the current computed CSS styles applied to an element. This may be the current value applied by an animation or as set by a stylesheet.","spec":"http://www.w3.org/TR/cssom/#dom-window-getcomputedstyle","status":"rec","links":[{"url":"http://snipplr.com/view/13523/","title":"Polyfill for IE"},{"url":"https://developer.mozilla.org/en/DOM/window.getComputedStyle","title":"MDN article"},{"url":"http://ie.microsoft.com/testdrive/HTML5/getComputedStyle/","title":"Demo"},{"url":"http://docs.webplatform.org/wiki/css/cssom/methods/getComputedStyle","title":"WebPlatform Docs"}],"categories":["DOM","JS API","CSS3"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"y","10":"y","11":"y"},"firefox":{"2":"n","3":"a","3.5":"a","3.6":"a","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"a","5":"a","6":"a","7":"a","8":"a","9":"a","10":"a","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"a","3.2":"a","4":"a","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"a","9.5-9.6":"a","10.0-10.1":"a","10.5":"a","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"a","4.0-4.1":"a","4.2-4.3":"a","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"a"},"android":{"2.1":"a","2.2":"a","2.3":"a","3":"a","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"a","10":"y"},"op_mob":{"10":"a","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"Partial support in older Firefox versions refers to requiring the second parameter to be included.\r\n\r\nPartial support in all other browsers refers to not supporting getComputedStyle on pseudo-elements.","notes_by_num":{},"usage_perc_y":83.58,"usage_perc_a":4.99,"ucprefix":false,"parent":"","keywords":""},"word-break":{"title":"CSS3 word-break","description":"Property to prevent or allow words to be broken over multiple lines between letters.","spec":"http://www.w3.org/TR/css3-text/#word-break","status":"wd","links":[{"url":"https://developer.mozilla.org/en/CSS/word-break","title":"MDN article"},{"url":"http://docs.webplatform.org/wiki/css/properties/word-break","title":"WebPlatform Docs"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"a","5":"a","6":"a","7":"a","8":"a","9":"a","10":"a","11":"a","12":"a","13":"a","14":"a","15":"a","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"a","24":"a","25":"a","26":"a","27":"a","28":"a","29":"a","30":"a","31":"a","32":"a","33":"a","34":"a","35":"a","36":"a","37":"a","38":"a","39":"a"},"safari":{"3.1":"a","3.2":"a","4":"a","5":"a","5.1":"a","6":"a","6.1":"a","7":"a","8":"a"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"a","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"a","24":"a"},"ios_saf":{"3.2":"a","4.0-4.1":"a","4.2-4.3":"a","5.0-5.1":"a","6.0-6.1":"a","7.0-7.1":"a","8":"a"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"a","2.2":"a","2.3":"a","3":"a","4":"a","4.1":"a","4.2-4.3":"a","4.4":"a","4.4.3":"a"},"bb":{"7":"a","10":"a"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"a"},"and_chr":{"36":"a"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"Partial support refers to supporting the \"break-all\" value, but not the \"keep-all\" value.","notes_by_num":{},"usage_perc_y":31.08,"usage_perc_a":57.88,"ucprefix":false,"parent":"","keywords":"break-all,keep-all"},"viewport-units":{"title":"Viewport units: vw, vh, vmin, vmax","description":"Length units representing 1% of the viewport size for viewport width (vw), height (vh), the smaller of the two (vmin), or the larger of the two (vmax).","spec":"http://www.w3.org/TR/css3-values/#viewport-relative-lengths","status":"cr","links":[{"url":"http://blog.rodneyrehm.de/archives/34-iOS7-Mobile-Safari-And-Viewport-Units.html","title":"Back-Forward issue blog post"},{"url":"https://github.com/saabi/vminpoly","title":"Polyfill"},{"url":"https://github.com/rodneyrehm/viewport-units-buggyfill","title":"Buggyfill - Polyfill that fixes buggy support"},{"url":"http://css-tricks.com/viewport-sized-typography/","title":"Blog post"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"a #2","10":"a #1","11":"a #1"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"a #1","21":"a #1","22":"a #1","23":"a #1","24":"a #1","25":"a #1","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"a #1","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"a #1","7.0-7.1":"a #3","8":"a #3"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"a #1"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"a #1"}},"notes":"Partial support in IE9 refers to supporting \"vm\" instead of \"vmin\". Partial support in IE10 refers to lack of \"vmax\" support. Partial support in iOS7 is due to buggy behavior of the \"vh\" unit. All other partial support refers to not supporting the \"vmax\" unit. ","notes_by_num":{},"usage_perc_y":55.64,"usage_perc_a":20.28,"ucprefix":false,"parent":"","keywords":"vm,viewport-percentage"},"contentsecuritypolicy":{"title":"Content Security Policy","description":"Mitigate cross-site scripting attacks by whitelisting allowed sources of script, style, and other resources.","spec":"http://www.w3.org/TR/CSP/","status":"cr","links":[{"url":"http://content-security-policy.com/","title":"CSP Examples & Quick Reference"},{"url":"http://html5rocks.com/en/tutorials/security/content-security-policy/","title":"HTML5Rocks article"}],"categories":["Other"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"a x","11":"a x"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"y x","5":"y x","6":"y x","7":"y x","8":"y x","9":"y x","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"a x","6":"y x","6.1":"y x","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"a x","6.0-6.1":"y x","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"y x"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"a x"}},"notes":"The HTTP header is 'X-Content-Security-Policy' for Firefox until version 23 and IE10&11, and 'X-Webkit-CSP' for Chrome until version 25 and Safari until version 7. 'Content-Security-Policy' is the official W3C defined header, used by Chrome version 25 and later, Firefox version 23 and later, and Safari 7 and later.","notes_by_num":{},"usage_perc_y":64.12,"usage_perc_a":11.08,"ucprefix":false,"parent":"","keywords":"csp,security,header"},"pagevisibility":{"title":"Page Visibility","description":"JavaScript API for determining whether a document is visible on the display","spec":"http://www.w3.org/TR/page-visibility/","status":"rec","links":[{"url":"http://docs.webplatform.org/wiki/apis/timing/properties/visibilityState","title":"WebPlatform Docs"},{"url":"https://developer.mozilla.org/en-US/docs/DOM/Using_the_Page_Visibility_API","title":"MDN article"},{"url":"http://aurelio.audero.it/demo/page-visibility-api-demo.html","title":"Demo"},{"url":"http://www.sitepoint.com/introduction-to-page-visibility-api/","title":"SitePoint article"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y x","17":"y x","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"y","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y x","4.4.3":"y x"},"bb":{"7":"n","10":"y x"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":73.47,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"visibilitystate"},"stricttransportsecurity":{"title":"Strict Transport Security","description":"Declare that a website is only accessible over a secure connection (HTTPS).","spec":"http://tools.ietf.org/html/rfc6797","status":"other","links":[{"url":"https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security","title":"MDN article"},{"url":"https://www.owasp.org/index.php/HTTP_Strict_Transport_Security","title":"OWASP article"},{"url":"http://dev.chromium.org/sts","title":"Chromium article"}],"categories":["Other"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"u","8":"u"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"The HTTP header is 'Strict-Transport-Security'.","notes_by_num":{"0":""},"usage_perc_y":57.46,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"sts,hsts,security,header"},"style-scoped":{"title":"Scoped CSS","description":"Allows CSS rules to be scoped to part of the document, based on the position of the style element.","spec":"http://www.w3.org/TR/html5/document-metadata.html#attr-style-scoped","status":"cr","links":[{"url":"https://github.com/PM5544/scoped-polyfill","title":"Polyfill"},{"url":"http://html5doctor.com/the-scoped-attribute/","title":"HTML5 Doctor article"},{"url":"http://updates.html5rocks.com/2012/03/A-New-Experimental-Feature-style-scoped","title":"HTML5Rocks article"}],"categories":["CSS","HTML5"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n d #1","21":"n d #1","22":"n d #1","23":"n d #1","24":"n d #1","25":"n d #1","26":"n d #1","27":"n d #1","28":"n d #1","29":"n d #1","30":"n d #1","31":"n d #1","32":"n d #1","33":"n d #1","34":"n d #1","35":"n d #1","36":"n d #1","37":"n","38":"n","39":"n"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"u","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{"1":"Enabled in Chrome though the \"experimental Web Platform features\" flag in chrome://flags"},"usage_perc_y":12.95,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"scope"},"svg-fragment":{"title":"SVG fragment identifiers","description":"Method of displaying only a part of an SVG image by defining a view ID or view box dimensions as the file's fragment identifier.","spec":"http://www.w3.org/TR/SVG/linking.html#SVGFragmentIdentifiers","status":"rec","links":[{"url":"http://www.broken-links.com/2012/08/14/better-svg-sprites-with-fragment-identifiers/","title":"Blog post"}],"categories":["SVG"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n","35":"n","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"a"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"a"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"u","22":"n"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"Partial support in Safari refers to supporting viewBox dimensions but not a view ID.","notes_by_num":{},"usage_perc_y":29.38,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"fragments,sprite"},"outline":{"title":"CSS outline","description":"The CSS outline property is a shorthand property for setting one or more of the individual outline properties outline-style, outline-width and outline-color in a single rule. In most cases the use of this shortcut is preferable and more convenient.","spec":"http://www.w3.org/TR/CSS2/ui.html#propdef-outline","status":"rec","links":[{"url":"https://developer.mozilla.org/en-US/docs/CSS/outline","title":"Mozilla Developer Network: outline"},{"url":"http://dev.w3.org/csswg/css3-ui/#outline","title":"CSS Basic User Interface Module Level 3"}],"categories":["CSS2"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"y","9":"y","10":"y","11":"y"},"firefox":{"2":"y","3":"y","3.5":"y","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"y","3.2":"y","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"y","9.5-9.6":"y","10.0-10.1":"y","10.5":"y","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"y","4.0-4.1":"y","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"y","2.2":"y","2.3":"y","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"y","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":89.84,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"-moz-outline,outline-width,outline-style,outline-color"},"download":{"title":"Download attribute","description":"When used on an anchor, this attribute signifies that the resource it points to should be downloaded by the browser rather than navigate to it.","spec":"http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#downloading-resources","status":"wd","links":[{"url":"http://updates.html5rocks.com/2011/08/Downloading-resources-in-HTML5-a-download","title":"HTML5Rocks post"},{"url":"http://html5-demos.appspot.com/static/a.download.html","title":"Demo: creating a text file and downloading it."}],"categories":["HTML5"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":54.26,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"download,a.download,a[download],download attribute"},"pointer":{"title":"Pointer events","description":"This specification integrates various inputs from mice, touchscreens, and pens, making separate implementations no longer necessary and authoring for cross-device pointers easier. Not to be mistaken with the unrelated \"pointer-events\" CSS property.","spec":"http://www.w3.org/TR/pointerevents/","status":"cr","links":[{"url":"http://blogs.msdn.com/b/ie/archive/2011/09/20/touch-input-for-ie10-and-metro-style-apps.aspx","title":"Implementation of Pointer Events in IE10"},{"url":"http://blogs.msdn.com/b/eternalcoding/archive/2013/01/16/hand-js-a-polyfill-for-supporting-pointer-events-on-every-browser.aspx","title":"Hand.js, the polyfill for browsers only supporting Touch Events"},{"url":"http://blogs.msdn.com/b/davrous/archive/2013/02/20/handling-touch-in-your-html5-apps-thanks-to-the-pointer-events-of-ie10-and-windows-8.aspx","title":"Article & tutorial"}],"categories":["DOM","JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"a x","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"p","7":"p","8":"p","9":"p","10":"p","11":"p","12":"p","13":"p","14":"p","15":"p","16":"p","17":"p","18":"p","19":"p","20":"p","21":"p","22":"p","23":"p","24":"p","25":"p","26":"p","27":"p","28":"p","29":"p","30":"p","31":"p","32":"p","33":"p","34":"p"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"p","23":"p","24":"p","25":"p","26":"p","27":"p","28":"p","29":"p","30":"p","31":"p","32":"p","33":"p","34":"p","35":"p","36":"p","37":"p","38":"p","39":"p"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"u","7":"u","8":"u"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"p","16":"p","17":"p","18":"p","19":"p","20":"p","21":"p","22":"p","23":"p","24":"p"},"ios_saf":{"3.2":"p","4.0-4.1":"p","4.2-4.3":"p","5.0-5.1":"p","6.0-6.1":"p","7.0-7.1":"p","8":"p"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"p","2.2":"p","2.3":"p","3":"p","4":"p","4.1":"p","4.2-4.3":"p","4.4":"p","4.4.3":"p"},"bb":{"7":"p","10":"p"},"op_mob":{"10":"n","11":"p","11.1":"p","11.5":"p","12":"p","12.1":"p","22":"p"},"and_chr":{"36":"p"},"and_ff":{"31":"p"},"ie_mob":{"10":"a x"}},"notes":"Partial support in IE10 refers the lack of pointerenter and pointerleave events. Firefox Nightly provides 'dom.w3c_pointer_events.enabled' option to support this specification starting with version 28.","notes_by_num":{},"usage_perc_y":7.18,"usage_perc_a":3.04,"ucprefix":false,"parent":"","keywords":"pointerdown,pointermove,pointerup,pointercancel,pointerover,pointerout,pointerenter,pointerleave"},"user-select-none":{"title":"CSS user-select: none","description":"Method of preventing text/element selection using CSS. ","spec":"https://developer.mozilla.org/en-US/docs/CSS/user-select","status":"unoff","links":[{"url":"http://msdn.microsoft.com/en-us/library/ie/hh781492(v=vs.85).aspx","title":"MSDN Documentation"},{"url":"https://developer.mozilla.org/en-US/docs/CSS/user-select","title":"MDN article"},{"url":"http://css-tricks.com/almanac/properties/u/user-select/","title":"CSS Tricks article"}],"categories":["CSS"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y x","11":"y x"},"firefox":{"2":"y x","3":"y x","3.5":"y x","3.6":"y x","4":"y x","5":"y x","6":"y x","7":"y x","8":"y x","9":"y x","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x"},"chrome":{"4":"u","5":"u","6":"y x","7":"y x","8":"y x","9":"y x","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x","35":"y x","36":"y x","37":"y x","38":"y x","39":"y x"},"safari":{"3.1":"y x","3.2":"y x","4":"y x","5":"y x","5.1":"y x","6":"y x","6.1":"y x","7":"y x","8":"y x"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x"},"ios_saf":{"3.2":"y x","4.0-4.1":"y x","4.2-4.3":"y x","5.0-5.1":"y x","6.0-6.1":"y x","7.0-7.1":"y x","8":"y x"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"y x","2.2":"y x","2.3":"y x","3":"y x","4":"y x","4.1":"y x","4.2-4.3":"y x","4.4":"y x","4.4.3":"y x"},"bb":{"7":"y x","10":"y x"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y x"},"and_chr":{"36":"y x"},"and_ff":{"31":"y x"},"ie_mob":{"10":"y x"}},"notes":"Currently the user-select property does not appear in any W3C specification. Support information here is only for \"none\" value, not others.","notes_by_num":{},"usage_perc_y":82.23,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":""},"webp":{"title":"WebP image format","description":"Image format that supports lossy and lossless compression, as well as animation and alpha transparency.","spec":"https://developers.google.com/speed/webp/","status":"other","links":[{"url":"http://antimatter15.github.io/weppy/demo.html","title":"Polyfill for browsers with WebM support"},{"url":"http://libwebpjs.appspot.com/","title":"Decoder in JS"},{"url":"https://developers.google.com/speed/webp/","title":"Official website"},{"url":"http://webpjs.appspot.com/","title":"Polyfill for browsers with or without WebM support (i.e. IE6-IE9, Safari/iOS version 6.1 and below; Firefox versions 24 and bel"},{"url":"https://developers.google.com/speed/webp/faq#which_web_browsers_natively_support_webp","title":"Official website FAQ - Which web browsers natively support WebP?"}],"categories":["Other"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"p","5":"p","6":"p","7":"p","8":"p","9":"p","10":"p","11":"p","12":"p","13":"p","14":"p","15":"p","16":"p","17":"p","18":"p","19":"p","20":"p","21":"p","22":"p","23":"p","24":"p","25":"p","26":"p","27":"p","28":"p","29":"p","30":"p","31":"p","32":"p","33":"p","34":"p"},"chrome":{"4":"n","5":"n","6":"p","7":"p","8":"p","9":"a","10":"a","11":"a","12":"a","13":"a","14":"a","15":"a","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"p","11":"p","11.1":"a","11.5":"a","11.6":"a","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"a","4.1":"a","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"a","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"Partial support in older Chrome, Opera and Android refers to browser not supporting lossless and alpha versions of WebP. Animated webp images are supported in Chrome 32+ and Opera 19+.","notes_by_num":{},"usage_perc_y":42.98,"usage_perc_a":3.87,"ucprefix":false,"parent":"","keywords":""},"intrinsic-width":{"title":"Intrinsic & Extrinsic Sizing","description":"Allows for the heights and widths to be specified in intrinsic values using the fill-available, max-content, min-content, and fit-content properties.","spec":"http://www.w3.org/TR/css3-sizing/","status":"wd","links":[{"url":"http://demosthenes.info/blog/662/Design-From-the-Inside-Out-With-CSS-MinContent","title":"Min-Content tutorial"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"y x","5":"y x","6":"y x","7":"y x","8":"y x","9":"y x","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x","35":"y x","36":"y x","37":"y x","38":"y x","39":"y x"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"y x","7":"y x","8":"y x"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"y x","8":"y x"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y x","4.4.3":"y x"},"bb":{"7":"n","10":"y x"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y x"},"and_chr":{"36":"y x"},"and_ff":{"31":"y x"},"ie_mob":{"10":"n"}},"notes":"Prefixes are on the values, not the property names (e.g. -webkit-min-content) Firefox currently supports the \"-moz-available\" property rather than \"-moz-fill-available\".","notes_by_num":{},"usage_perc_y":62.45,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"fill-available,max-content,min-content,fit-content,contain-floats"},"template":{"title":"HTML templates","description":"Method of declaring a portion of reusable markup that is parsed but not rendered until cloned.","spec":"http://www.w3.org/TR/html5/scripting-1.html#the-template-element","status":"wd","links":[{"url":"http://www.html5rocks.com/en/tutorials/webcomponents/template/","title":"HTML5Rocks - HTML's New template Tag"},{"url":"http://polymer-project.org","title":"Polymer project (polyfill & web components framework)"}],"categories":["HTML5","DOM"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":53.04,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"web components, template"},"opus":{"title":"Opus","description":"Royalty-free open audio codec by IETF, which incorporated SILK from Skype and CELT from Xiph.org, to serve higher sound quality and lower latency at the same bitrate.","spec":"http://tools.ietf.org/html/rfc6716","status":"other","links":[{"url":"https://hacks.mozilla.org/2012/07/firefox-beta-15-supports-the-new-opus-audio-format/","title":"Introduction of Opus by Mozilla"},{"url":"http://www.ietf.org/mail-archive/web/rtcweb/current/msg04953.html","title":"Google's statement about the use of VP8 and Opus codec for WebRTC standard"}],"categories":["Other"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"For Opera the Linux version may be able to play it when the GStreamer module is up to date and the served mime-type is 'audio/ogg'.","notes_by_num":{},"usage_perc_y":44.75,"usage_perc_a":0,"ucprefix":false,"parent":"audio","keywords":""},"jpegxr":{"title":"JPEG XR image format","description":"The latest JPEG image format of Joint Photographic Experts Group which boasts better compression and supports lossless compression, alpha channel, and 48-bit deep color over normal jpg format.","spec":"http://www.itu.int/rec/T-REC-T.832","status":"other","links":[{"url":"http://msdn.microsoft.com/en-us/library/windows/desktop/hh707223(v=vs.85).aspx","title":"Microsoft JPEG XR Codec Overview"}],"categories":["Other"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"y","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n","35":"n","36":"n","37":"n","38":"n","39":"n"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"n"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":12.82,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":""},"channel-messaging":{"title":"Channel messaging","description":"Method for having two-way communication between browsing contexts (using MessageChannel)","spec":"http://www.w3.org/TR/webmessaging/#channel-messaging","status":"cr","links":[{"url":"http://dev.opera.com/articles/view/window-postmessage-messagechannel/#channel","title":"An Introduction to HTML5 web messaging"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"u","10.0-10.1":"u","10.5":"u","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"u","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"n"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":62.39,"usage_perc_a":0,"ucprefix":false,"parent":"x-doc-messaging","keywords":""},"css3-tabsize":{"title":"CSS3 tab-size","description":"Method of customizing the width of the tab character. Only effective using 'white-space: pre' or 'white-space: pre-wrap'.","spec":"http://www.w3.org/TR/css3-text/#tab-size1","status":"wd","links":[{"url":"https://developer.mozilla.org/en-US/docs/Web/CSS/tab-size","title":"MDN article"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"y x","5":"y x","6":"y x","7":"y x","8":"y x","9":"y x","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"y x","11":"y x","11.1":"y x","11.5":"y x","11.6":"y x","12":"y x","12.1":"y x","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"n","11":"y x","11.1":"y x","11.5":"y x","12":"y x","12.1":"y x","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y x"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":63.43,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"tab-size,tab-width"},"mutationobserver":{"title":"Mutation Observer","description":"Method for observing and reacting to changes to the DOM. Replaces MutationEvents, which is deprecated.","spec":"http://www.w3.org/TR/dom/","status":"wd","links":[{"url":"https://github.com/Polymer/MutationObservers","title":"Polyfill"},{"url":"https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver","title":"MutationObserver from MDN"}],"categories":["DOM","JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"p","10":"p","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"y x","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"y x","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"p","4.1":"p","4.2-4.3":"p","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"y x"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"p"}},"notes":"When the content of a node with a single CharacterData child node is changed by innerHTML attribute and the node have a single different one as a result, WebKit browsers consider it as a characterData mutation of the child CharacterData node, while other browsers think it as a childList mutation of the parent node.","notes_by_num":{},"usage_perc_y":70.7,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"MutationObserver"},"css-selection":{"title":"::selection CSS pseudo-element","description":"The ::selection CSS pseudo-element applies rules to the portion of a document that has been highlighted (e.g., selected with the mouse or another pointing device) by the user.","spec":"https://developer.mozilla.org/en-US/docs/Web/CSS/::selection","status":"unoff","links":[{"url":"http://quirksmode.org/css/selectors/selection.html","title":"::selection test"},{"url":"http://docs.webplatform.org/wiki/css/selectors/pseudo-elements/::selection","title":"WebPlatform Docs"}],"categories":["CSS"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"y","10":"y","11":"y"},"firefox":{"2":"y x","3":"y x","3.5":"y x","3.6":"y x","4":"y x","5":"y x","6":"y x","7":"y x","8":"y x","9":"y x","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"y","3.2":"y","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"y","10.0-10.1":"y","10.5":"y","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"u","11":"u","11.1":"u","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"n"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":72.46,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"::selection,selection"},"css-placeholder":{"title":":placeholder-shown CSS pseudo-class","description":"The :placeholder-shown pseudo-class represents the placeholder contents of a form field with placeholder text.","spec":"http://dev.w3.org/csswg/selectors/#placeholder","status":"unoff","links":[{"url":"http://css-tricks.com/snippets/css/style-placeholder-text/","title":"CSS-Tricks article with all prefixes"},{"url":"http://wiki.csswg.org/ideas/placeholder-styling","title":"CSSWG discussion"},{"url":"http://msdn.microsoft.com/en-us/library/ie/hh772745(v=vs.85).aspx","title":"MSDN article"}],"categories":["CSS"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"a x","11":"a x"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"a x","5":"a x","6":"a x","7":"a x","8":"a x","9":"a x","10":"a x","11":"a x","12":"a x","13":"a x","14":"a x","15":"a x","16":"a x","17":"a x","18":"a x","19":"a x","20":"a x","21":"a x","22":"a x","23":"a x","24":"a x","25":"a x","26":"a x","27":"a x","28":"a x","29":"a x","30":"a x","31":"a x","32":"a x","33":"a x","34":"a x"},"chrome":{"4":"a x","5":"a x","6":"a x","7":"a x","8":"a x","9":"a x","10":"a x","11":"a x","12":"a x","13":"a x","14":"a x","15":"a x","16":"a x","17":"a x","18":"a x","19":"a x","20":"a x","21":"a x","22":"a x","23":"a x","24":"a x","25":"a x","26":"a x","27":"a x","28":"a x","29":"a x","30":"a x","31":"a x","32":"a x","33":"a x","34":"a x","35":"a x","36":"a x","37":"a x","38":"a x","39":"a x"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"a x","5.1":"a x","6":"a x","6.1":"a x","7":"a x","8":"a x"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"a x","16":"a x","17":"a x","18":"a x","19":"a x","20":"a x","21":"a x","22":"a x","23":"a x","24":"a x"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"a x","5.0-5.1":"a x","6.0-6.1":"a x","7.0-7.1":"a x","8":"a x"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"a x","2.2":"a x","2.3":"a x","3":"a x","4":"a x","4.1":"a x","4.2-4.3":"a x","4.4":"a x","4.4.3":"a x"},"bb":{"7":"u","10":"a x"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"a x"},"and_chr":{"36":"a x"},"and_ff":{"31":"a x"},"ie_mob":{"10":"a x"}},"notes":"Partial support refers to support for alternative syntax: ::-webkit-input-placeholder (Chrome/Safari/Opera),\r\n::-moz-placeholder (Firefox) and \r\n:-ms-input-placeholder (IE). ","notes_by_num":{},"usage_perc_y":0,"usage_perc_a":81.79,"ucprefix":false,"parent":"","keywords":"::placeholder,placeholder"},"canvas-blending":{"title":"Canvas blend modes","description":"Method of defining the effect resulting from overlaying two layers on a Canvas element. ","spec":"http://www.w3.org/TR/compositing-1/#blending","status":"wd","links":[{"url":"http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/","title":"Blog post"}],"categories":["Canvas"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":60.08,"usage_perc_a":0,"ucprefix":false,"parent":"canvas","keywords":""},"clipboard":{"title":"Clipboard API","description":"API to provide copy, cut and paste functionality using the OS clipboard.","spec":"http://www.w3.org/TR/clipboard-apis/","status":"wd","links":[{"url":"https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent","title":"MDN page on ClipboardEvent"},{"url":"http://www.deluxeblogtips.com/2010/06/javascript-copy-to-clipboard.html","title":"Blog post on cross-browser usage"}],"categories":["JS API"],"stats":{"ie":{"5.5":"a #1","6":"a #1","7":"a #1","8":"a #1","9":"a #1","10":"a #1","11":"a #1"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"a","14":"a","15":"a","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"a","24":"a","25":"a","26":"a","27":"a","28":"a","29":"a","30":"a","31":"a","32":"a","33":"a","34":"a","35":"a","36":"a","37":"a","38":"a","39":"a"},"safari":{"3.1":"u","3.2":"u","4":"a","5":"a","5.1":"a","6":"a","6.1":"a","7":"a","8":"a"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"a","17":"a","18":"a","19":"a","20":"a","21":"a","22":"a","23":"a","24":"a"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"a","6.0-6.1":"a","7.0-7.1":"a","8":"a"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"a","4.4.3":"a"},"bb":{"7":"n","10":"a"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"a"},"and_chr":{"36":"a"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"Partial support in IE refers using [a non-standard method](http://msdn.microsoft.com/en-us/library/ie/ms535220%28v=vs.85%29.aspx) of interacting with the clipboard. For other browsers it refers to not supporting the ClipboardEvent constructor.","notes_by_num":{},"usage_perc_y":12.69,"usage_perc_a":68.69,"ucprefix":false,"parent":"","keywords":"cut,copy,paste,clipboarddata"},"rtcpeerconnection":{"title":"WebRTC Peer-to-peer connections","description":"Method of allowing two users to communicate directly, browser to browser using the RTCPeerConnection API.","spec":"http://www.w3.org/TR/webrtc/#peer-to-peer-connections","status":"wd","links":[{"url":"http://www.webrtc.org/","title":"WebRTC Project site"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x","35":"y x","36":"y x","37":"y x","38":"y x","39":"y x"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y x"},"and_chr":{"36":"y x"},"and_ff":{"31":"y x"},"ie_mob":{"10":"n"}},"notes":"BlackBerry 10 recognizes RTCPeerConnection but real support is unconfirmed.","notes_by_num":{},"usage_perc_y":52.23,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":""},"css3-cursors":{"title":"CSS3 Cursors (original values)","description":"CSS3 cursor values added in the 2004 spec, including none, context-menu, cell, vertical-text, alias, copy, no-drop, not-allowed, nesw-resize, nwse-resize, col-resize, row-resize and all-scroll. ","spec":"http://www.w3.org/TR/css3-ui/#cursor","status":"wd","links":[{"url":"https://developer.mozilla.org/en-US/docs/Web/CSS/cursor","title":"MDN Documentation"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"a","6":"a","7":"a","8":"a","9":"a","10":"a","11":"a"},"firefox":{"2":"a","3":"a","3.5":"a","3.6":"a","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"a","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"a","3.2":"a","4":"a","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"a","9.5-9.6":"a","10.0-10.1":"a","10.5":"a","10.6":"a","11":"a","11.1":"a","11.5":"a","11.6":"a","12":"a","12.1":"a","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"u"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"Internet Explorer does not support the alias, cell, copy, ew-resize, ns-resize, nesw-resize, nwse-resize or context-menu cursors. Opera 12.10- does not support 'none' or a URI.","notes_by_num":{},"usage_perc_y":52.27,"usage_perc_a":18.12,"ucprefix":false,"parent":"","keywords":"cursors, pointers"},"webvtt":{"title":"WebVTT - Web Video Text Tracks","description":"Format for marking up text captions for multimedia resources.","spec":"http://dev.w3.org/html5/webvtt/","status":"unoff","links":[{"url":"http://www.html5rocks.com/en/tutorials/track/basics/","title":"Getting Started With the Track Element"},{"url":"http://dev.opera.com/articles/view/an-introduction-to-webvtt-and-track/","title":"An Introduction to WebVTT and track"}],"categories":["Other"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n d","25":"n d","26":"n d","27":"n d","28":"n d","29":"n d","30":"n d","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"WebVTT must be used with the <track> element.\r\n\r\nFirefox currently lacks support for the for ::cue pseudoelement.","notes_by_num":{},"usage_perc_y":59.51,"usage_perc_a":0,"ucprefix":false,"parent":"video","keywords":"captions,track"},"promises":{"title":"Promises","description":"A promise represents the eventual result of an asynchronous operation.","spec":"https://people.mozilla.org/~jorendorff/es6-draft.html#sec-promise-objects","status":"other","links":[{"url":"http://promises-aplus.github.io/promises-spec/","title":"Promises/A+ spec"},{"url":"http://www.html5rocks.com/en/tutorials/es6/promises/","title":"JavaScript Promises: There and back again - HTML5 Rocks"},{"url":"https://github.com/jakearchibald/ES6-Promises","title":"A polyfill for ES6-style Promises"},{"url":"http://www.chromestatus.com/features/5681726336532480","title":"Chromium dashboard - ES6 Promises"}],"categories":["DOM","JS API"],"stats":{"ie":{"5.5":"p","6":"p","7":"p","8":"p","9":"p","10":"p","11":"p"},"firefox":{"2":"p","3":"p","3.5":"p","3.6":"p","4":"p","5":"p","6":"p","7":"p","8":"p","9":"p","10":"p","11":"p","12":"p","13":"p","14":"p","15":"p","16":"p","17":"p","18":"p","19":"p","20":"p","21":"p","22":"p","23":"p","24":"p","25":"p","26":"p","27":"a","28":"a","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"p","5":"p","6":"p","7":"p","8":"p","9":"p","10":"p","11":"p","12":"p","13":"p","14":"p","15":"p","16":"p","17":"p","18":"p","19":"p","20":"p","21":"p","22":"p","23":"p","24":"p","25":"p","26":"p","27":"p","28":"p","29":"p","30":"p","31":"p","32":"a","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"p","3.2":"p","4":"p","5":"p","5.1":"p","6":"p","6.1":"p","7":"p","8":"y"},"opera":{"9":"p","9.5-9.6":"p","10.0-10.1":"p","10.5":"p","10.6":"p","11":"p","11.1":"p","11.5":"p","11.6":"p","12":"p","12.1":"p","15":"p","16":"p","17":"p","18":"p","19":"a","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"p","4.0-4.1":"p","4.2-4.3":"p","5.0-5.1":"p","6.0-6.1":"p","7.0-7.1":"p","8":"y"},"op_mini":{"5.0-7.0":"p"},"android":{"2.1":"p","2.2":"p","2.3":"p","3":"p","4":"p","4.1":"p","4.2-4.3":"p","4.4":"p","4.4.3":"p"},"bb":{"7":"p","10":"p"},"op_mob":{"10":"p","11":"p","11.1":"p","11.5":"p","12":"p","12.1":"p","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"p"}},"notes":"","notes_by_num":{},"usage_perc_y":48.46,"usage_perc_a":0.98,"ucprefix":false,"parent":"","keywords":"futures"},"css-sticky":{"title":"CSS position:sticky","description":"Keeps elements positioned as \"fixed\" or \"relative\" depending on how it appears in the viewport. As a result the element is \"stuck\" when necessary while scrolling.","spec":"http://dev.w3.org/csswg/css-position/#sticky-positioning","status":"unoff","links":[{"url":"https://github.com/filamentgroup/fixed-sticky","title":"Polyfill"},{"url":"https://developer.mozilla.org/en-US/docs/Web/CSS/position","title":"MDN article"},{"url":"http://updates.html5rocks.com/2012/08/Stick-your-landings-position-sticky-lands-in-WebKit","title":"HTML5Rocks"},{"url":"http://docs.webplatform.org/wiki/css/properties/position","title":"WebPlatform Docs"}],"categories":["CSS"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n d #1","27":"n d #1","28":"n d #1","29":"n d #1","30":"n d #1","31":"n d #1","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n d #2","24":"n d #2","25":"n d #2","26":"n d #2","27":"n d #2","28":"n d #2","29":"n d #2","30":"n d #2","31":"n d #2","32":"n d #2","33":"n d #2","34":"n d #2","35":"n d #2","36":"n d #2","37":"n","38":"n","39":"n"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"y x","7":"y x","8":"y x"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"y x","7.0-7.1":"y x","8":"y x"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{"2":"Enabled in Chrome though the \"experimental Web Platform features\" flag in chrome://flags","1":"Can be enabled in Firefox by setting the about:config preference layout.css.sticky.enabled to true"},"usage_perc_y":8.66,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":""},"css-variables":{"title":"CSS Variables","description":"Permits the declaration and usage of cascading variables in stylesheets.","spec":"http://www.w3.org/TR/css-variables/","status":"wd","links":[{"url":"https://hacks.mozilla.org/2013/12/css-variables-in-firefox-nightly/","title":"Mozilla hacks article (older syntax)"},{"url":"https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables","title":"MDN article"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n","35":"n","36":"n","37":"u","38":"u","39":"u"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":0.33,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"css variables"},"vibration":{"title":"Vibration API","description":"Method to access the vibration mechanism of the hosting device.","spec":"http://www.w3.org/TR/vibration/","status":"wd","links":[{"url":"http://davidwalsh.name/vibration-api","title":"Vibration API sample code & demo"},{"url":"http://aurelio.audero.it/demo/vibration-api-demo.html","title":"Demo"},{"url":"http://code.tutsplus.com/tutorials/html5-vibration-api--mobile-22585","title":"Tuts+ article"},{"url":"https://developer.mozilla.org/en-US/docs/Web/Guide/API/Vibration","title":"MDN article"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":52.81,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"vibration,mobile,device"},"css-backgroundblendmode":{"title":"CSS background-blend-mode","description":"Allows blending between CSS background images, gradients, and colors.","spec":"http://www.w3.org/TR/compositing-1/#background-blend-mode","status":"cr","links":[{"url":"https://medium.com/web-design-technique/6b51bf53743a","title":"Blog post"},{"url":"http://bennettfeely.com/gradients","title":"Demo"},{"url":"http://codepen.io/bennettfeely/pen/rxoAc","title":"codepen example"}],"categories":["CSS"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":39.57,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"css blend modes,css blending modes,blending,multiply,screen,background"},"css-mixblendmode":{"title":"Blending of HTML/SVG elements","description":"Allows blending between arbitrary SVG and HTML elements","spec":"http://www.w3.org/TR/compositing-1/#mix-blend-mode","status":"cr","links":[{"url":"http://css-tricks.com/basics-css-blend-modes/","title":"Blog post"},{"url":"http://codepen.io/bennettfeely/pen/csjzd","title":"codepen example"}],"categories":["CSS"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n d #1","30":"n d #1","31":"n d #1","32":"n d #1","33":"n d #1","34":"n d #1","35":"n d #1","36":"n d #1","37":"n d #1","38":"n d #1","39":"n d #1"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{"1":"Enabled in Chrome though the \"experimental Web Platform features\" flag in chrome://flags"},"usage_perc_y":0.02,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"css blend modes,css blending modes"},"web-speech":{"title":"Web Speech API","description":"Method to provide speech input and text-to-speech output features in a web browser.","spec":"https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html","status":"unoff","links":[{"url":"http://updates.html5rocks.com/2013/01/Voice-Driven-Web-Apps-Introduction-to-the-Web-Speech-API","title":"HTML5Rocks article"},{"url":"http://aurelio.audero.it/demo/web-speech-api-demo.html","title":"Demo"},{"url":"http://zenorocha.github.io/voice-elements/","title":"Advanced demo and resource"},{"url":"http://www.sitepoint.com/introducing-web-speech-api/","title":"SitePoint article"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"a x","26":"a x","27":"a x","28":"a x","29":"a x","30":"a x","31":"a x","32":"a x","33":"a x","34":"a x","35":"a x","36":"a x","37":"a x","38":"a x","39":"a x"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"a x","7":"a x","8":"a x"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"a x","8":"a x"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"a x"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"Partial support in Chrome refers to some attributes missing. Partial support in Safari refers to only Speech Synthesis supported.","notes_by_num":{},"usage_perc_y":0,"usage_perc_a":46.77,"ucprefix":false,"parent":"","keywords":"speech,recognition,ASR"},"high-resolution-time":{"title":"High Resolution Time API","description":"Method to provide the current time in sub-millisecond resolution and such that it is not subject to system clock skew or adjustments. Called using performance.now()","spec":"http://www.w3.org/TR/hr-time/","status":"rec","links":[{"url":"http://aurelio.audero.it/demo/high-resolution-time-api-demo.html","title":"Demo"},{"url":"https://developer.mozilla.org/en-US/docs/Web/API/Performance.now()","title":"MDN article"},{"url":"http://updates.html5rocks.com/2012/08/When-milliseconds-are-not-enough-performance-now","title":"HTML5Rocks article"},{"url":"http://www.sitepoint.com/discovering-the-high-resolution-time-api/","title":"SitePoint article"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"y x","21":"y x","22":"y x","23":"y x","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":64.65,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"performance,now,testing"},"battery-status":{"title":"Battery Status API","description":"Method to provide information about the battery status of the hosting device.","spec":"http://www.w3.org/TR/battery-status/","status":"cr","links":[{"url":"https://developer.mozilla.org/en-US/docs/WebAPI/Battery_Status","title":"MDN Docs"},{"url":"http://www.smartjava.org/examples/webapi-battery/","title":"Simple demo"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n","35":"n","36":"n","37":"n","38":"n","39":"n"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"Support has already landed in Webkit but it is yet to make into Android and Chrome [android issue](https://code.google.com/p/chromium/issues/detail?id=135863) [chrome issue](https://code.google.com/p/chromium/issues/detail?id=122593)","notes_by_num":{},"usage_perc_y":13.72,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":""},"text-decoration":{"title":"text-decoration styling","description":"Method of defining the type, style and color of lines in the text-decoration property.","spec":"http://www.w3.org/TR/css-text-decor-3/#line-decoration","status":"cr","links":[{"url":"https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-style","title":"MDN Documentation for text-decoration-style"},{"url":"https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-line","title":"MDN Documentation for text-decoration-line"},{"url":"https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-color","title":"MDN Documentation for text-decoration-color"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"y x","7":"y x","8":"y x","9":"y x","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n x d #1","27":"n x d #1","28":"n x d #1","29":"n x d #1","30":"n x d #1","31":"n x d #1","32":"n x d #1","33":"n x d #1","34":"n x d #1","35":"n x d #1","36":"n x d #1","37":"n x d #1","38":"n x d #1","39":"n x d #1"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"y x"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{"1":"Enabled in Chrome though the \"experimental Web Platform features\" flag in chrome://flags"},"usage_perc_y":13.86,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"text-decoration-line,text-decoration-style,text-decoration-color"},"speech-synthesis":{"title":"Speech Synthesis API","description":"A web API for controlling a text-to-speech output.","spec":"https://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#tts-section","status":"unoff","links":[{"url":"http://updates.html5rocks.com/2014/01/Web-apps-that-talk---Introduction-to-the-Speech-Synthesis-API","title":"HTML5Rocks article"},{"url":"http://aurelio.audero.it/demo/speech-synthesis-api-demo.html","title":"Demo"},{"url":"http://www.sitepoint.com/talking-web-pages-and-the-speech-synthesis-api/","title":"SitePoint article"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"y"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":43.69,"usage_perc_a":0,"ucprefix":false,"parent":"web-speech","keywords":"speech,synthesis,speechSynthesis,TTS,SpeechSynthesisUtterance,"},"user-timing":{"title":"User Timing API","description":"Method to help web developers measure the performance of their applications by giving them access to high precision timestamps.","spec":"http://www.w3.org/TR/user-timing/","status":"rec","links":[{"url":"http://aurelio.audero.it/demo/user-timing-api-demo.html","title":"Demo"},{"url":"http://www.sitepoint.com/discovering-user-timing-api/","title":"SitePoint article"},{"url":"https://gist.github.com/pmeenan/5902672","title":"Polyfill"},{"url":"http://www.html5rocks.com/en/tutorials/webperformance/usertiming/","title":"HTML5Rocks article"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"n"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":50.63,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"performance,testing,mark,measure"},"srcset":{"title":"Srcset attribute","description":"Allows authors to specify alternate high-resolution sources on elements","spec":"http://picture.responsiveimages.org/#relationship-to-srcset","status":"other","links":[{"url":"https://www.webkit.org/blog/2910/improved-support-for-high-resolution-displays-with-the-srcset-image-attribute/","title":"Improved support for high-resolution displays with the srcset image attribute"}],"categories":["HTML5"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"This covers the stand-alone `srcset` syntax for resolution switching, not the expanded syntax to be used in concert with `sizes`.","notes_by_num":{},"usage_perc_y":36.02,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":""},"ambient-light":{"title":"Ambient Light API","description":"Defines events that provide information about the ambient light level, as measured by a device's light sensor.","spec":"http://www.w3.org/TR/ambient-light/","status":"cr","links":[{"url":"http://aurelio.audero.it/demo/ambient-light-api-demo.html","title":"Demo"},{"url":"http://flippinawesome.org/2014/05/27/introduction-to-the-ambient-light-api/","title":"Article"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"a","23":"a","24":"a","25":"a","26":"a","27":"a","28":"a","29":"a","30":"a","31":"a","32":"a","33":"a","34":"a"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n","35":"n","36":"n","37":"n","38":"n","39":"n"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"a"},"ie_mob":{"10":"n"}},"notes":"Partial support in Firefox refers to the fact that only the devicelight event is supported. In addition, Firefox desktop supports this API only on Mac OS X. [Support for Windows 7 is in progress](https://bugzilla.mozilla.org/show_bug.cgi?id=754199)","notes_by_num":{},"usage_perc_y":0,"usage_perc_a":12.69,"ucprefix":false,"parent":"","keywords":""},"css-shapes":{"title":"CSS Shapes Level 1","description":"Allows geometric shapes to be set in CSS to define an area for text to flow around.","spec":"http://www.w3.org/TR/css-shapes/","status":"cr","links":[{"url":"http://html.adobe.com/webplatform/layout/shapes/","title":"Adobe demos and samples"},{"url":"http://alistapart.com/article/css-shapes-101","title":"A List Apart article"},{"url":"http://html.adobe.com/webplatform/layout/shapes/browser-support/","title":"CSS shapes support test by Adobe"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n d #1","35":"n d #1","36":"n d #1","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"y x"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"y x"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{"1":"Enabled in Chrome though the \"experimental Web Platform features\" flag in chrome://flags"},"usage_perc_y":0.15,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"circle,ellipse,polygon,inset,shape-outside,shape-inside"},"domcontentloaded":{"title":"DOMContentLoaded","description":"JavaScript event, fired when the dom is loaded, but not yet stylesheets or images","spec":"http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html","status":"other","links":[{"url":"https://developer.mozilla.org/en-US/docs/Web/Reference/Events/DOMContentLoaded","title":"MDN: DOMContentLoaded"}],"categories":["DOM"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"y","10":"y","11":"y"},"firefox":{"2":"y","3":"y","3.5":"y","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"y","3.2":"y","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"y","9.5-9.6":"y","10.0-10.1":"y","10.5":"y","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"y","4.0-4.1":"y","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"y"},"android":{"2.1":"y","2.2":"y","2.3":"y","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"y","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":88.57,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"dom,domready,onload,contentloaded,document"},"proximity":{"title":"Proximity API","description":"Defines events that provide information about the distance between a device and an object, as measured by a proximity sensor.","spec":"http://www.w3.org/TR/proximity/","status":"cr","links":[{"url":"http://aurelio.audero.it/demo/proximity-api-demo.html","title":"Demo"},{"url":"http://www.sitepoint.com/introducing-proximity-api/","title":"SitePoint article"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n","35":"n","36":"n","37":"n","38":"n","39":"n"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":13.37,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":""},"kerning-pairs-ligatures":{"title":"Improved kerning pairs & ligatures","description":"Currently non-standard method of improving kerning pairs & ligatures using text-rendering: optimizeLegibility.","spec":"http://www.w3.org/TR/SVG11/painting.html#TextRenderingProperty","status":"unoff","links":[{"url":"https://developer.mozilla.org/en-US/docs/Web/CSS/text-rendering","title":"MDN article"},{"url":"http://css-tricks.com/almanac/properties/t/text-rendering/","title":"CSS Tricks article"}],"categories":["CSS"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"y","3.5":"y","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"u","4.0-4.1":"u","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"y"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":70.7,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"optimizeLegibility,optimizeSpeed,geometricPrecision"},"iframe-seamless":{"title":"seamless attribute for iframes","description":"The seamless attribute makes an iframe's contents actually part of a page, and adopts the styles from its hosting page. ","spec":"http://whatwg.org/html#attr-iframe-seamless","status":"cr","links":[{"url":"https://github.com/ornj/seamless-polyfill","title":"Experimental polyfill"},{"url":"http://labs.ft.com/2013/01/seamless-iframes-not-quite-seamless/","title":"Article"}],"categories":["HTML5"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"u","33":"u","34":"u"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n d","21":"n d","22":"n d","23":"n d","24":"n d","25":"n d","26":"n d","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n","35":"n","36":"n","37":"u","38":"u","39":"u"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"u"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"u","24":"u"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"u"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"u"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"Chrome 20-26 had partial support behind a flag, though this was [later removed](http://crbug.com/229421). \r\n\r\nSafari 7 (& iOS 7 Safari) hides the border of seamless iframes and recognizes the 'seamless' DOM property, but does not provide actual support.","notes_by_num":{},"usage_perc_y":0,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":""},"css-image-orientation":{"title":"CSS3 image-orientation","description":"CSS property used generally to fix the intended orientation of an image. This can be done using 90 degree increments or based on the image's EXIF data using the \"from-image\" value.","spec":"http://www.w3.org/TR/css3-images/#image-orientation","status":"cr","links":[{"url":"http://sethfowler.org/blog/2013/09/13/new-in-firefox-26-css-image-orientation/","title":"Blog post"},{"url":"http://jsbin.com/EXUTolo/4","title":"Demo (Chinese)"},{"url":"https://developer.mozilla.org/en-US/docs/Web/CSS/image-orientation","title":"MDN article"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n","35":"n","36":"n","37":"n","38":"n","39":"n"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"a","4.0-4.1":"a","4.2-4.3":"a","5.0-5.1":"a","6.0-6.1":"a","7.0-7.1":"a","8":"a"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"Partial support in iOS refers to the browser using EXIF data by default, though it does not actually support the property. Opening the image in a new tab in Chrome results in the image shown in the orientation according to the EXIF data.","notes_by_num":{},"usage_perc_y":12.22,"usage_perc_a":6.66,"ucprefix":false,"parent":"","keywords":"image-orientation,from-image,flip"},"picture":{"title":"Picture element","description":"A responsive images method to control which image resource a user agent presents to a user, based on resolution, media query and/or support for a particular image format","spec":"http://www.w3.org/TR/html-picture-element/","status":"wd","links":[{"url":"http://responsiveimages.org/","title":"General information about Responsive Images"},{"url":"http://usecases.responsiveimages.org/","title":"Read about the use cases"},{"url":"http://responsiveimages.org/demos/","title":"Demo"},{"url":"http://code.tutsplus.com/tutorials/better-responsive-images-with-the-picture-element--net-36583","title":"Tutorial"},{"url":"http://www.w3.org/TR/html-picture-element/","title":"Latest RICG <picture> specification"}],"categories":["HTML5","DOM"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"y","34":"y"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n","35":"n","36":"n","37":"n d #1","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"u"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{"1":"Enabled in Chrome though the \"experimental Web Platform features\" flag in chrome://flags"},"usage_perc_y":0.01,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":""},"woff2":{"title":"WOFF 2.0 - A better web font compression format","description":"TrueType/OpenType font that provides better compression than WOFF 1.0.","spec":"http://www.w3.org/TR/WOFF2/","status":"wd","links":[{"url":"https://gist.github.com/sergejmueller/cf6b4f2133bcb3e2f64a","title":"Basics about WOFF 2.0"}],"categories":["Other"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n","35":"n","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"y"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":5.79,"usage_perc_a":0,"ucprefix":false,"parent":"fontface","keywords":"woff, fontface, webfonts"},"text-size-adjust":{"title":"CSS text-size-adjust","description":"On mobile devices, the text-size-adjust CSS property allows Web authors to control if and how the text-inflating algorithm is applied to the textual content of the element it is applied to.","spec":"http://dev.w3.org/csswg/css-size-adjust/","status":"wd","links":[{"url":"https://developer.mozilla.org/en-US/docs/Web/CSS/text-size-adjust","title":"MDN Docs"}],"categories":["CSS3"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n","35":"n","36":"n","37":"n","38":"n","39":"n"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"y x","6.0-6.1":"y x","7.0-7.1":"y x","8":"y x"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"n"},"and_ff":{"31":"y x"},"ie_mob":{"10":"y x"}},"notes":"","notes_by_num":{},"usage_perc_y":7.14,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":""},"web-animation":{"title":"Web Animations API","description":"This function lets you create an animation purely in JavaScript and have it run as efficiently as any CSS Animation or Transition.","spec":"http://dev.w3.org/fxtf/web-animations/","status":"wd","links":[{"url":"http://updates.html5rocks.com/2014/05/Web-Animations---element-animate-is-now-in-Chrome-36","title":"HTML5 Rocks"},{"url":"http://updates.html5rocks.com/2013/12/New-Web-Animations-engine-in-Blink-drives-CSS-Animations-Transitions","title":"HTML5 Rocks"}],"categories":["DOM","JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n","35":"n","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"n"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"y"},"and_ff":{"31":"n"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":5.79,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"js,animation,animate"},"resource-timing":{"title":"Resource Timing","description":"Method to help web developers to collect complete timing information related to resources on a document.","spec":"http://www.w3.org/TR/resource-timing/","status":"cr","links":[{"url":"http://googledevelopers.blogspot.com/2013/12/measuring-network-performance-with.html","title":"Blog post"},{"url":"http://aurelio.audero.it/demo/resource-timing-api-demo.html","title":"Demo"},{"url":"http://www.sitepoint.com/introduction-resource-timing-api/","title":"SitePoint article"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"n"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"n","6.1":"n","7":"n","8":"n"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8":"n"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"y","4.4.3":"y"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"n"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{"0":""},"usage_perc_y":50.63,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"performance,testing,resource"},"custom-elements":{"title":"Custom Elements","description":"Method of defining and using new types of DOM elements in a document.","spec":"http://www.w3.org/TR/custom-elements/","status":"wd","links":[{"url":"http://w3c.github.io/webcomponents/spec/custom/","title":"W3C Editor's Draft spec (closer to current implementations)"},{"url":"https://code.google.com/p/chromium/issues/detail?id=234509","title":"Chromium tracking bug: Implement Custom Elements"},{"url":"https://bugzilla.mozilla.org/show_bug.cgi?id=889230","title":"Firefox tracking bug: Implement Custom Elements (from Web Components)"},{"url":"http://status.modern.ie/customelements","title":"IE Web Platform Status and Roadmap: Custom Elements"},{"url":"http://www.html5rocks.com/tutorials/webcomponents/customelements/","title":"HTML5Rocks - Custom Elements: defining new elements in HTML"},{"url":"http://www.polymer-project.org/platform/custom-elements.html","title":"Polymer project (polyfill & web components framework)"}],"categories":["HTML5","DOM"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"p","11":"p"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"p","30":"p","31":"p","32":"p","33":"p","34":"p"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"p","6.1":"p","7":"p","8":"p"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"p","8":"p"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"u"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":37.02,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"web components"},"imports":{"title":"HTML Imports","description":"Method of including and reusing HTML documents in other HTML documents.","spec":"http://www.w3.org/TR/html-imports/","status":"wd","links":[{"url":"http://status.modern.ie/htmlimports","title":"IE Web Platform Status and Roadmap: HTML Imports"},{"url":"http://www.html5rocks.com/tutorials/webcomponents/imports/","title":"HTML5Rocks - HTML Imports: #include for the web"},{"url":"https://code.google.com/p/chromium/issues/detail?id=240592","title":"Chromium tracking bug: Implement HTML Imports"},{"url":"https://bugzilla.mozilla.org/show_bug.cgi?id=877072","title":"Firefox tracking bug: Implement HTML Imports"},{"url":"http://www.polymer-project.org/platform/html-imports.html","title":"Polymer project (polyfill & web components framework)"}],"categories":["HTML5","DOM"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"p","11":"p"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"p","30":"p","31":"p","32":"p","33":"p","34":"p"},"chrome":{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"n","29":"n","30":"n","31":"n","32":"n","33":"n","34":"p","35":"p","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"n","5":"n","5.1":"n","6":"p","6.1":"p","7":"p","8":"p"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"p","22":"p","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"p","8":"p"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"n","2.2":"n","2.3":"n","3":"n","4":"n","4.1":"n","4.2-4.3":"n","4.4":"n","4.4.3":"u"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"n"},"and_chr":{"36":"y"},"and_ff":{"31":"p"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{},"usage_perc_y":5.79,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"web components"},"input-file-multiple":{"title":"Multiple file selection","description":"Allows users to select multiple files in the file picker.","spec":"http://www.w3.org/TR/html5/forms.html#attr-input-multiple","status":"wd","links":[{"url":"http://www.raymondcamden.com/2012/2/28/Working-with-HTML5s-multiple-file-upload-support","title":"Article"},{"url":"https://code.google.com/p/chromium/issues/detail?id=348912","title":"Chrome bug (for Android)"}],"categories":["HTML5"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"n","3":"n","3.5":"n","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"n","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"n","3.2":"n","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"n #1"},"android":{"2.1":"n #1","2.2":"n #1","2.3":"n #1","3":"n #1","4":"n #1","4.1":"n #1","4.2-4.3":"n #1","4.4":"n #1","4.4.3":"n #1"},"bb":{"7":"n","10":"n"},"op_mob":{"10":"n #1","11":"n #1","11.1":"n #1","11.5":"n #1","12":"n #1","12.1":"n #1","22":"n #1"},"and_chr":{"36":"n #1"},"and_ff":{"31":"n #1"},"ie_mob":{"10":"n"}},"notes":"","notes_by_num":{"1":"Not supported when tested on Android, presumably an OS limitation. "},"usage_perc_y":69.16,"usage_perc_a":0,"ucprefix":false,"parent":"forms","keywords":""},"atob-btoa":{"title":"Base64 encoding and decoding","description":"Utility functions for of encoding and decoding strings to and from base 64: window.atob() and window.btoa().","spec":"http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#atob","status":"other","links":[{"url":"https://github.com/davidchambers/Base64.js","title":"Polyfill"},{"url":"https://developer.mozilla.org/en-US/docs/Web/API/Window.atob","title":"MDN article on atob()"},{"url":"https://developer.mozilla.org/en-US/docs/Web/API/Window.btoa","title":"MDN article on btoa()"}],"categories":["JS API"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"y","11":"y"},"firefox":{"2":"y","3":"y","3.5":"y","3.6":"y","4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y"},"chrome":{"4":"y","5":"y","6":"y","7":"y","8":"y","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y"},"safari":{"3.1":"y","3.2":"y","4":"y","5":"y","5.1":"y","6":"y","6.1":"y","7":"y","8":"y"},"opera":{"9":"n","9.5-9.6":"u","10.0-10.1":"u","10.5":"u","10.6":"y","11":"y","11.1":"y","11.5":"y","11.6":"y","12":"y","12.1":"y","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y"},"ios_saf":{"3.2":"y","4.0-4.1":"y","4.2-4.3":"y","5.0-5.1":"y","6.0-6.1":"y","7.0-7.1":"y","8":"y"},"op_mini":{"5.0-7.0":"y"},"android":{"2.1":"y","2.2":"y","2.3":"y","3":"y","4":"y","4.1":"y","4.2-4.3":"y","4.4":"y","4.4.3":"y"},"bb":{"7":"y","10":"y"},"op_mob":{"10":"u","11":"y","11.1":"y","11.5":"y","12":"y","12.1":"y","22":"y"},"and_chr":{"36":"y"},"and_ff":{"31":"y"},"ie_mob":{"10":"y"}},"notes":"","notes_by_num":{},"usage_perc_y":85.94,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":"atob,btoa"},"css-appearance":{"title":"CSS Appearance","description":"The `appearance` property defines how elements (particularly form controls) appear by default. By setting the value to `none` the default appearance can be entirely redefined using other CSS properties.","spec":"http://wiki.csswg.org/spec/css4-ui#appearance","status":"unoff","links":[{"url":"http://css-tricks.com/almanac/properties/a/appearance/","title":"CSS Tricks article"}],"categories":["CSS"],"stats":{"ie":{"5.5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n"},"firefox":{"2":"y x","3":"y x","3.5":"y x","3.6":"y x","4":"y x","5":"y x","6":"y x","7":"y x","8":"y x","9":"y x","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x"},"chrome":{"4":"y x","5":"y x","6":"y x","7":"y x","8":"y x","9":"y x","10":"y x","11":"y x","12":"y x","13":"y x","14":"y x","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x","25":"y x","26":"y x","27":"y x","28":"y x","29":"y x","30":"y x","31":"y x","32":"y x","33":"y x","34":"y x","35":"y x","36":"y x","37":"y x","38":"y x","39":"y x"},"safari":{"3.1":"y x","3.2":"y x","4":"y x","5":"y x","5.1":"y x","6":"y x","6.1":"y x","7":"y x","8":"y x"},"opera":{"9":"n","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11":"n","11.1":"n","11.5":"n","11.6":"n","12":"n","12.1":"n","15":"y x","16":"y x","17":"y x","18":"y x","19":"y x","20":"y x","21":"y x","22":"y x","23":"y x","24":"y x"},"ios_saf":{"3.2":"y x","4.0-4.1":"y x","4.2-4.3":"y x","5.0-5.1":"y x","6.0-6.1":"y x","7.0-7.1":"y x","8":"y x"},"op_mini":{"5.0-7.0":"n"},"android":{"2.1":"y x","2.2":"y x","2.3":"y x","3":"y x","4":"y x","4.1":"y x","4.2-4.3":"y x","4.4":"y x","4.4.3":"y x"},"bb":{"7":"y x","10":"y x"},"op_mob":{"10":"n","11":"n","11.1":"n","11.5":"n","12":"n","12.1":"n","22":"y x"},"and_chr":{"36":"y x"},"and_ff":{"31":"y x"},"ie_mob":{"10":"n"}},"notes":"The `appearance` property currently does not appear in any CSS specification so there is no specifically correct usage.","notes_by_num":{},"usage_perc_y":72.05,"usage_perc_a":0,"ucprefix":false,"parent":"","keywords":""}}}
================================================
FILE: core/data/caniuse_extras/css-placeholder.json
================================================
{
"title":"::placeholder CSS pseudo-element",
"description":"The ::placeholder pseudo-element represents any form element displaying placeholder text.",
"spec":"https://developer.mozilla.org/en-US/docs/Web/CSS/::-moz-placeholder",
"status":"unoff",
"links":[
{
"url":"http://css-tricks.com/snippets/css/style-placeholder-text/",
"title":"CSS-Tricks article with all prefixes"
},
{
"url":"http://wiki.csswg.org/ideas/placeholder-styling",
"title":"CSSWG discussion"
},
{
"url":"http://msdn.microsoft.com/en-us/library/ie/hh772745(v=vs.85).aspx",
"title":"MSDN article"
}
],
"bugs":[
],
"categories":[
"CSS"
],
"stats":{
"ie":{
"5.5":"n",
"6":"n",
"7":"n",
"8":"n",
"9":"n",
"10":"y x",
"11":"y x"
},
"firefox":{
"2":"n",
"3":"n",
"3.5":"n",
"3.6":"n",
"4":"y x",
"5":"y x",
"6":"y x",
"7":"y x",
"8":"y x",
"9":"y x",
"10":"y x",
"11":"y x",
"12":"y x",
"13":"y x",
"14":"y x",
"15":"y x",
"16":"y x",
"17":"y x",
"18":"y x",
"19":"y x",
"20":"y x",
"21":"y x",
"22":"y x",
"23":"y x",
"24":"y x",
"25":"y x",
"26":"y x"
},
"chrome":{
"4":"y x",
"5":"y x",
"6":"y x",
"7":"y x",
"8":"y x",
"9":"y x",
"10":"y x",
"11":"y x",
"12":"y x",
"13":"y x",
"14":"y x",
"15":"y x",
"16":"y x",
"17":"y x",
"18":"y x",
"19":"y x",
"20":"y x",
"21":"y x",
"22":"y x",
"23":"y x",
"24":"y x",
"25":"y x",
"26":"y x",
"27":"y x",
"28":"y x",
"29":"y x",
"30":"y x",
"31":"y x",
"32":"y x"
},
"safari":{
"3.1":"n",
"3.2":"n",
"4":"n",
"5":"y x",
"5.1":"y x",
"6":"y x",
"7":"y x"
},
"opera":{
"9":"n",
"9.5-9.6":"n",
"10.0-10.1":"n",
"10.5":"n",
"10.6":"n",
"11":"n",
"11.1":"n",
"11.5":"n",
"11.6":"n",
"12":"n",
"12.1":"n",
"15":"y x",
"16":"a",
"17":"a"
},
"ios_saf":{
"3.2":"n",
"4.0-4.1":"n",
"4.2-4.3":"y x",
"5.0-5.1":"y x",
"6.0-6.1":"y x",
"7.0":"y x"
},
"op_mini":{
"5.0-7.0":"n"
},
"android":{
"2.1":"u",
"2.2":"u",
"2.3":"u",
"3":"u",
"4":"u",
"4.1":"u",
"4.2":"u"
},
"bb":{
"7":"u",
"10":"u"
},
"op_mob":{
"10":"n",
"11":"n",
"11.1":"n",
"11.5":"n",
"12":"n",
"12.1":"n",
"14":"y x"
},
"and_chr":{
"0":"y x"
},
"and_ff":{
"0":"n"
},
"ie_mob":{
"10":"y x"
}
},
"notes":"",
"usage_perc_y":70.21,
"usage_perc_a":0.18,
"ucprefix":false,
"parent":"",
"keywords":"::placeholder,placeholder",
"shown":false
}
================================================
FILE: core/lib/compass/browser_support.rb
================================================
module Compass
module BrowserSupport
extend self
ASPECTS = %w(webkit moz o ms svg css2)
SIMPLE_FUNCTIONS = {
"image" => %w(webkit),
"cross-fade" => %w(webkit),
"repeating-linear-gradient" => %w(webkit moz), # Hacky implementation
"repeating-radial-gradient" => %w(webkit moz) # Hacky implementation
}
# Adds support for one or more aspects for the given simple function
# Example:
#
# Compass::BrowserSupport.add_support("image", "moz", "webkit")
# # => Adds support for moz and webkit to the image() function.
#
# This function can be called one or more times in a compass configuration
# file in order to add support for new, simple browser functions without
# waiting for a new compass release.
def add_support(function, *aspects)
aspects.each do |aspect|
unless ASPECTS.include?(aspect)
Compass::Util.compass_warn "Unknown support aspect: #{aspect}"
next
end
unless supports?(function, aspect)
SIMPLE_FUNCTIONS[function.to_s] ||= []
SIMPLE_FUNCTIONS[function.to_s] << aspect.to_s
end
end
end
# Removes support for one or more aspects for the given simple function
# Example:
#
# Compass::BrowserSupport.remove_support("image", "o", "ms")
# # => Adds support for moz and webkit to the image() function.
#
# This function can be called one or more times in a compass configuration
# file in order to remove support for simple functions that no longer need to
# a prefix without waiting for a new compass release.
def remove_support(function, *aspects)
aspects.each do |aspect|
unless ASPECTS.include?(aspect)
Compass::Util.compass_warn "Unknown support aspect: #{aspect}"
next
end
SIMPLE_FUNCTIONS[function.to_s].reject!{|a| a == aspect.to_s}
end
end
def supports?(function, aspect)
SIMPLE_FUNCTIONS.has_key?(function.to_s) && SIMPLE_FUNCTIONS[function.to_s].include?(aspect.to_s)
end
def has_aspect?(function)
SIMPLE_FUNCTIONS.has_key?(function.to_s) && SIMPLE_FUNCTIONS[function.to_s].size > 0
end
end
end
================================================
FILE: core/lib/compass/configuration/adapters.rb
================================================
module Compass
module Configuration
# The adapters module provides methods that make configuration data from a compass project
# adapt to various consumers of configuration data
module Adapters
def to_compiler_arguments(additional_options = {})
engine_opts = to_sass_engine_options.merge(additional_options)
# we have to pass the quiet option in the nested :sass hash to disambiguate it from the compass compiler's own quiet option.
if engine_opts.has_key?(:quiet)
engine_opts[:sass] ||= {}
engine_opts[:sass][:quiet] = engine_opts.delete(:quiet)
end
[project_path, sass_path, css_path, engine_opts]
end
def to_sass_plugin_options
locations = []
locations << [sass_path, css_path] if sass_path && css_path
Compass::Frameworks::ALL.each do |framework|
locations << [framework.stylesheets_directory, File.join(css_path || css_dir || ".", framework.name)]
end
plugin_opts = {:template_location => locations}
plugin_opts[:style] = output_style if output_style
plugin_opts[:line_comments] = line_comments
if sass_3_4?
plugin_opts[:sourcemap] = sourcemap ? :auto : :none
else
plugin_opts[:sourcemap] = sourcemap
end
plugin_opts[:cache] = cache unless cache.nil?
plugin_opts[:cache_location] = cache_path unless cache_path.nil?
plugin_opts[:quiet] = disable_warnings if disable_warnings
plugin_opts[:compass] = {}
plugin_opts[:compass][:environment] = environment
plugin_opts.merge!(sass_options || {})
plugin_opts[:load_paths] ||= []
plugin_opts[:load_paths] += resolve_additional_import_paths
# TODO: When sprites are extracted to their own plugin, this
# TODO: will need to be extracted to there.
if defined?(Compass::SpriteImporter.new)
plugin_opts[:load_paths] << Compass::SpriteImporter.new
end
plugin_opts[:full_exception] = (environment == :development)
plugin_opts
end
def resolve_additional_import_paths
(additional_import_paths || []).map do |path|
if path.is_a?(String) && project_path && !absolute_path?(path)
File.join(project_path, path)
else
path
end
end
end
def absolute_path?(path)
# Pretty basic implementation
path.index(File::SEPARATOR) == 0 || path.index(':') == 1
end
def to_sass_engine_options
engine_opts = {:load_paths => sass_load_paths}
engine_opts[:style] = output_style if output_style
engine_opts[:line_comments] = line_comments
if sass_3_4?
engine_opts[:sourcemap] = sourcemap ? :auto : :none
else
engine_opts[:sourcemap] = sourcemap
end
engine_opts[:cache] = cache
engine_opts[:cache_location] = cache_path
engine_opts[:quiet] = disable_warnings if disable_warnings
engine_opts[:compass] = {}
engine_opts[:compass][:environment] = environment
engine_opts[:full_exception] = (environment == :development)
engine_opts.merge!(sass_options || {})
end
def sass_load_paths
load_paths = []
load_paths << sass_path if sass_path && File.directory?(sass_path)
Compass::Frameworks::ALL.each do |f|
load_paths << f.stylesheets_directory if File.directory?(f.stylesheets_directory)
end
importer = sass_options[:filesystem_importer] if sass_options && sass_options[:filesystem_importer]
importer ||= Sass::Importers::Filesystem
load_paths += resolve_additional_import_paths
load_paths.map! do |p|
next p if p.respond_to?(:find_relative)
importer.new(p.to_s)
end
# TODO: When sprites are extracted to their own plugin, this
# TODO: will need to be extracted to there.
if defined?(Compass::SpriteImporter.new)
load_paths << Compass::SpriteImporter.new
end
load_paths
end
def sass_3_4?
Sass.version[:major] == 3 && Sass.version[:minor] == 4
end
end
class Data
include Adapters
end
end
end
================================================
FILE: core/lib/compass/configuration/data.rb
================================================
module Compass
module Configuration
# The Compass configuration data storage class manages configuration data that comes from a variety of
# different sources and aggregates them together into a consistent API
# Some of the possible sources of configuration data:
# * Compass default project structure for stand alone projects
# * App framework specific project structures for rails, etc.
# * User supplied explicit configuration
# * Configuration data provided via the command line interface
#
# There are two kinds of configuration data that doesn't come from the user:
#
# 1. Configuration data that is defaulted as if the user had provided it themselves.
# This is useful for providing defaults that the user is likely to want to edit
# but shouldn't have to provide explicitly when getting started
# 2. Configuration data that is defaulted behind the scenes because _some_ value is
# required.
class Data
attr_reader :name
extend Sass::Callbacks
include Compass::Configuration::Inheritance
extend Compass::Configuration::Paths
# on_sprite_saved
# yields the filename
# usage: on_sprite_saved {|filename| do_something(filename) }
define_callback :sprite_saved
chained_method :run_sprite_saved
# on_sprite_generated
# yields 'ChunkyPNG::Image'
# usage: on_sprite_generated {|sprite_data| do_something(sprite_data) }
define_callback :sprite_generated
chained_method :run_sprite_generated
# on_sprite_removed
# yields the filename
# usage: on_sprite_removed {|filename| do_something(filename) }
define_callback :sprite_removed
chained_method :run_sprite_removed
# on_stylesheet_saved
# yields the filename
# usage: on_stylesheet_saved {|filename| do_something(filename) }
define_callback :stylesheet_saved
chained_method :run_stylesheet_saved
# on_sourcemap_saved
# yields the filename
# usage: on_sourcemap_saved {|filename| do_something(filename) }
define_callback :sourcemap_saved
chained_method :run_sourcemap_saved
# on_stylesheet_removed
# yields the filename
# usage: on_stylesheet_removed {|filename| do_something(filename) }
define_callback :stylesheet_removed
chained_method :run_stylesheet_removed
# on_sourcemap_removed
# yields the filename
# usage: on_sourcemap_removed {|filename| do_something(filename) }
define_callback :sourcemap_removed
chained_method :run_sourcemap_removed
# on_stylesheet_error
# yields the filename & message
# usage: on_stylesheet_error {|filename, message| do_something(filename, message) }
define_callback :stylesheet_error
chained_method :run_stylesheet_error
inherited_accessor(*ATTRIBUTES)
strip_trailing_separator(*ATTRIBUTES.select{|a| a.to_s =~ /dir|path/})
ARRAY_ATTRIBUTES.each do |array_attr|
inherited_array(array_attr, ARRAY_ATTRIBUTE_OPTIONS.fetch(array_attr, {}))
end
def initialize(name, attr_hash = nil)
raise "I need a name!" unless name
@name = name
set_all(attr_hash) if attr_hash
self.top_level = self
end
def set_all(attr_hash)
attr_hash.each do |a, v|
if self.respond_to?("#{a}=")
self.send("#{a}=", v)
end
end
end
def add_import_path(*paths)
paths.map!{|p| defined?(Pathname) && Pathname === p ? p.to_s : p}
# The @added_import_paths variable works around an issue where
# the additional_import_paths gets overwritten during parse
@added_import_paths ||= []
@added_import_paths += paths
paths.each do |p|
self.additional_import_paths << p unless additional_import_paths.include?(p)
end
end
# When called with a block, defines the asset host url to be used.
# The block must return a string that starts with a protocol (E.g. http).
# The block will be passed the root-relative url of the asset.
# When called without a block, returns the block that was previously set.
def asset_host(&block)
@set_attributes ||= {}
if block_given?
@set_attributes[:asset_host] = true
@asset_host = block
else
if @asset_host
@asset_host
elsif inherited_data.respond_to?(:asset_host)
inherited_data.asset_host
end
end
end
# When called with a block, defines the cache buster strategy to be used.
# If the block returns nil or a string, then it is appended to the url as a query parameter.
# In this case, the returned string must not include the starting '?'.
# The block may also return a hash with :path and/or :query values and it
# will replace the original path and query string with the busted values returned.
# The block will be passed the root-relative url of the asset.
# If the block accepts two arguments, it will also be passed a File object
# that points to the asset on disk -- which may or may not exist.
# When called without a block, returns the block that was previously set.
#
# To disable the asset cache buster:
#
# asset_cache_buster :none
def asset_cache_buster(simple = nil, &block)
@set_attributes ||= {}
if block_given?
@set_attributes[:asset_cache_buster] = true
@asset_cache_buster = block
elsif !simple.nil?
if simple == :none
@set_attributes[:asset_cache_buster] = true
@asset_cache_buster = Proc.new {|_,_| nil}
else
raise ArgumentError, "Unexpected argument: #{simple.inspect}"
end
else
if set?(:asset_cache_buster)
@asset_cache_buster
elsif inherited_data.respond_to?(:asset_cache_buster)
inherited_data.asset_cache_buster
end
end
end
def watch(glob, &block)
@watches ||= []
@watches << Watch.new(glob, &block)
end
def watches
if defined?(@watches)
@watches
elsif inherited_data.respond_to?(:watches)
inherited_data.watches
else
[]
end
end
# Require a compass plugin and capture that it occured so that the configuration serialization works next time.
def require(lib)
(self.required_libraries ||= []) << lib
super
end
def load(framework_dir)
(self.loaded_frameworks ||= []) << framework_dir
Compass::Frameworks.register_directory framework_dir
end
# Finds all extensions within a directory and registers them.
def discover(frameworks_dir)
(self.framework_path ||= []) << frameworks_dir
Compass::Frameworks.discover frameworks_dir
end
def relative_assets?
# the http_images_path is deprecated, but here for backwards compatibility.
relative_assets || http_images_path == :relative
end
end
end
end
================================================
FILE: core/lib/compass/configuration/defaults.rb
================================================
module Compass
module Configuration
module Defaults
def default_project_path
"."
end
def default_project_type
:stand_alone
end
def default_http_path
"/"
end
def default_extensions_dir
"extensions"
end
def default_css_dir
"stylesheets"
end
def default_sass_dir
"sass"
end
def default_fonts_dir
"fonts"
end
def default_images_dir
"images"
end
def default_environment
:development
end
def default_output_style
if top_level.environment == :development
:expanded
else
:compressed
end
end
def default_line_comments
top_level.environment == :development
end
def default_color_output
true
end
def default_sass_path
if (pp = top_level.project_path) && (dir = top_level.sass_dir)
Compass.projectize(dir, pp)
end
end
def default_css_path
if (pp = top_level.project_path) && (dir = top_level.css_dir)
Compass.projectize(dir, pp)
end
end
def default_images_path
if (pp = top_level.project_path) && (dir = top_level.images_dir)
Compass.projectize(dir, pp)
end
end
def default_generated_images_path
if (pp = top_level.project_path) && (dir = top_level.generated_images_dir)
Compass.projectize(dir, pp)
else
top_level.images_path
end
end
def default_javascripts_path
if (pp = top_level.project_path) && (dir = top_level.javascripts_dir)
Compass.projectize(dir, pp)
end
end
def default_extensions_path
if (pp = top_level.project_path) && (dir = top_level.extensions_dir)
Compass.projectize(dir, pp)
end
end
def default_fonts_path
if (pp = top_level.project_path) && (dir = top_level.fonts_dir)
Compass.projectize(dir, pp)
end
end
def default_cache_dir
".sass-cache"
end
def default_cache_path
if (pp = top_level.project_path) && (dir = top_level.cache_dir_without_default)
Compass.projectize(dir, pp)
# TODO We should make Sass::Plugin.options a configuration source instead of
# TODO one-offing it like this.
elsif defined?(Sass::Plugin) && Sass::Plugin.options[:cache_location]
File.expand_path(Sass::Plugin.options[:cache_location])
elsif (pp = top_level.project_path) && (dir = top_level.cache_dir)
Compass.projectize(dir, pp)
end
end
def default_generated_images_dir
top_level.images_dir
end
def default_http_generated_images_dir
top_level.http_images_dir
end
def default_http_images_dir
top_level.images_dir
end
def default_sprite_load_path
[top_level.images_path]
end
def default_http_images_path
http_root_relative top_level.http_images_dir
end
def default_http_stylesheets_dir
top_level.css_dir
end
def default_http_stylesheets_path
http_root_relative top_level.http_stylesheets_dir
end
def default_http_generated_images_path
http_root_relative top_level.http_generated_images_dir
end
def default_http_fonts_dir
top_level.fonts_dir
end
def default_http_fonts_path
http_root_relative top_level.http_fonts_dir
end
def default_http_javascripts_dir
top_level.javascripts_dir
end
def default_http_javascripts_path
http_root_relative top_level.http_javascripts_dir
end
def default_cache
true
end
def default_preferred_syntax
:scss
end
def default_sprite_engine
:chunky_png
end
def default_chunky_png_options
if defined?(::Zlib)
{:compression => Zlib::BEST_COMPRESSION}
else
{}
end
end
# helper functions
def http_join(*segments)
segments.map do |segment|
next unless segment
segment = http_pathify(segment)
segment[-1..-1] == "/" ? segment[0..-2] : segment
end.join("/")
end
def http_pathify(path)
if File::SEPARATOR == "/"
path
else
path.gsub(File::SEPARATOR, "/")
end
end
def http_root_relative(path)
http_join top_level.http_path, path
end
end
end
end
================================================
FILE: core/lib/compass/configuration/inheritance.rb
================================================
module Compass
module Configuration
# The inheritance module makes it easy for configuration data to inherit from
# other instances of configuration data. This makes it easier for external code to layer
# bits of configuration from various sources.
module Inheritance
def self.included(base)
# inherited_data stores configuration data that this configuration object will
# inherit if not provided explicitly.
base.send :attr_accessor, :inherited_data, :set_attributes, :top_level
base.send(:include, InstanceMethods)
base.extend(ClassMethods)
end
module ClassMethods
def inherited_writer(*attributes)
attributes.each do |attribute|
line = __LINE__ + 1
class_eval %Q{
def #{attribute}=(value) # def css_dir=(value)
@set_attributes ||= {} # @set_attributes ||= {}
@set_attributes[#{attribute.inspect}] = true # @set_attributes[:css_dir] = true
@#{attribute} = value # @css_dir = value
end # end
def unset_#{attribute}! # def unset_css_dir!
unset!(#{attribute.inspect}) # unset!(:css_dir)
end # end
def #{attribute}_set? # def css_dir_set?
set?(#{attribute.inspect}) # set?(:css_dir)
end # end
}, __FILE__, line
end
end
# Defines the default reader to be an inherited_reader that will look at the inherited_data for its
# value when not set. The inherited reader calls to a raw reader that acts like a normal attribute
# reader but prefixes the attribute name with "raw_".
def inherited_reader(*attributes)
attributes.each do |attribute|
line = __LINE__ + 1
class_eval %Q{
def raw_#{attribute} # def raw_css_dir
@#{attribute} # @css_dir
end # end
def #{attribute}_without_default # def css_dir_without_default
read_without_default(#{attribute.inspect}) # read_without_default(:css_dir)
end # end
def #{attribute} # def css_dir
read(#{attribute.inspect}) # read(:css_dir)
end # end
}, __FILE__, line
end
end
def inherited_accessor(*attributes)
inherited_reader(*attributes)
inherited_writer(*attributes)
end
class ArrayProxy
def initialize(data, attr)
@data, @attr = data, attr
end
def to_ary
@data.send(:"read_inherited_#{@attr}_array")
end
def to_a
to_ary
end
def <<(v)
@data.send(:"add_to_#{@attr}", v)
end
def >>(v)
@data.send(:"remove_from_#{@attr}", v)
end
def serialize_to_config(prop)
if v = @data.raw(prop)
"#{prop} = #{v.inspect}"
else
s = ""
if added = @data.instance_variable_get("@added_to_#{@attr}")
added.each do |a|
s << "#{prop} << #{a.inspect}\n"
end
end
if removed = @data.instance_variable_get("@removed_from_#{@attr}")
removed.each do |r|
s << "#{prop} >> #{r.inspect}\n"
end
end
if s[-1..-1] == "\n"
s[0..-2]
else
s
end
end
end
def method_missing(m, *args, &block)
a = to_ary
if a.respond_to?(m)
a.send(m,*args, &block)
else
super
end
end
end
def inherited_array(*attributes)
options = attributes.last.is_a?(Hash) ? attributes.pop : {}
inherited_reader(*attributes)
inherited_writer(*attributes)
attributes.each do |attr|
line = __LINE__ + 1
class_eval %Q{
def #{attr} # def sprite_load_paths
ArrayProxy.new(self, #{attr.inspect}) # ArrayProxy.new(self, :sprite_load_paths)
end # end
def #{attr}=(value) # def sprite_load_paths=(value)
@set_attributes ||= {} # @set_attributes ||= {}
@set_attributes[#{attr.inspect}] = true # @set_attributes[:sprite_load_paths] = true
@#{attr} = Array(value) # @sprite_load_paths = Array(value)
@added_to_#{attr} = [] # @added_to_sprite_load_paths = []
@removed_from_#{attr} = [] # @removed_from_sprite_load_paths = []
end # end
def read_inherited_#{attr}_array # def read_inherited_sprite_load_paths_array
value = if inherited_data # value = if inherited_data
if #{!!options[:clobbers]} && #{attr}_set?
Array(@#{attr}) # Array(@#{attr})
else
Array(@#{attr}) + inherited_data.read_inherited_#{attr}_array # inherited_data.read_inherited_sprite_load_paths_array + Array(@sprite_load_paths)
end
elsif #{attr}_set? # elsif sprite_load_paths_set?
Array(@#{attr}) # Array(@#{attr})
else # else
top_level.default_for(#{attr.inspect}) || [] # top_level.default_for(:sprite_load_paths) || []
end # end
value -= Array(@removed_from_#{attr}) # value -= Array(@removed_from_sprite_load_paths)
Array(@added_to_#{attr}) + value # Array(@added_to_sprite_load_paths) + value
end # end
def add_to_#{attr}(v) # def add_to_sprite_load_paths(v)
if #{attr}_set? # if sprite_load_paths_set?
raw_#{attr} << v # raw_sprite_load_paths << v
else # else
(@added_to_#{attr} ||= []) << v # (@added_to_sprite_load_paths ||= []) << v
end # end
end # end
def remove_from_#{attr}(v) # def remove_from_sprite_load_paths(v)
if #{attr}_set? # if sprite_load_paths_set?
raw_#{attr}.reject!{|e| e == v} # raw_sprite_load_path.reject!{|e| e == v}s
else # else
(@removed_from_#{attr} ||= []) << v # (@removed_from_sprite_load_paths ||= []) << v
end # end
end # end
}, __FILE__, line
end
end
def chained_method(method)
line = __LINE__ + 1
class_eval %Q{
alias_method :_chained_#{method}, method
def #{method}(*args, &block)
_chained_#{method}(*args, &block)
if inherited_data
inherited_data.#{method}(*args, &block)
end
end
}, __FILE__, line
end
end
module InstanceMethods
def on_top!
self.set_top_level(self)
end
def set_top_level(new_top)
self.top_level = new_top
if self.inherited_data.respond_to?(:set_top_level)
self.inherited_data.set_top_level(new_top)
end
end
def inherit_from!(data)
if self.inherited_data
self.inherited_data.inherit_from!(data)
else
self.inherited_data = data
end
self
end
def reset_inheritance!
self.inherited_data = nil
end
def with_defaults(data)
inherit_from!(data)
yield
reset_inheritance!
end
def unset!(attribute)
@set_attributes ||= {}
send("#{attribute}=", nil)
@set_attributes.delete(attribute)
nil
end
def set?(attribute)
@set_attributes ||= {}
@set_attributes[attribute]
end
def any_attributes_set?
@set_attributes && @set_attributes.size > 0
end
def default_for(attribute)
method = "default_#{attribute}".to_sym
if respond_to?(method)
send(method)
end
end
# Read an explicitly set value that is either inherited or set on this instance
def read_without_default(attribute)
if set?(attribute)
send("raw_#{attribute}")
elsif inherited_data.nil?
nil
elsif inherited_data.respond_to?("#{attribute}_without_default")
inherited_data.send("#{attribute}_without_default")
elsif inherited_data.respond_to?(attribute)
inherited_data.send(attribute)
end
end
# Reads the raw value that was set on this object.
# you generally should call raw_() instead.
def raw(attribute)
instance_variable_get("@#{attribute}")
end
# Read a value that is either inherited or set on this instance, if we get to the bottom-most configuration instance,
# we ask for the default starting at the top level.
def read(attribute)
if !(v = send("#{attribute}_without_default")).nil?
v
else
top_level.default_for(attribute)
end
end
def method_missing(meth, *args, &block)
if inherited_data
inherited_data.send(meth, *args, &block)
else
raise NoMethodError, meth.to_s
end
end
def respond_to?(meth)
if super
true
elsif inherited_data
inherited_data.respond_to?(meth)
else
false
end
end
def chain
instances = [self]
instances << instances.last.inherited_data while instances.last.inherited_data
instances
end
def debug
normalized_attrs = {}
(ATTRIBUTES + ARRAY_ATTRIBUTES).each do |prop|
values = []
chain.each do |instance|
values << {
:raw => (instance.send("raw_#{prop}") rescue nil),
:value => (instance.send("#{prop}_without_default") rescue nil),
:default => (instance.send("default_#{prop}") rescue nil),
:resolved => instance.send(prop)
}
end
normalized_attrs[prop] = values
end
normalized_attrs
end
end
end
end
end
================================================
FILE: core/lib/compass/configuration/paths.rb
================================================
module Compass::Configuration::Paths
TRAILING_SEPARATOR = %r{.(/|#{Regexp.escape(File::SEPARATOR)})$}
def strip_trailing_separator(*attributes)
attributes.each do |attr|
alias_method "#{attr}_with_trailing_separator".to_sym, attr
class_eval %Q{
def #{attr} # def css_dir
path = #{attr}_with_trailing_separator # path = css_dir_with_trailing_separator
if path.to_s =~ TRAILING_SEPARATOR # if path =~ TRAILING_SEPARATOR
path = path[0..-($1.length+1)] # path = path[0..-($1.length+1)]
end # end
path # path
end # end
}
end
end
end
================================================
FILE: core/lib/compass/configuration/watch.rb
================================================
module Compass
module Configuration
class Watch
attr_reader :callback
attr_reader :glob
attr_reader :full_glob
def initialize(glob, &block)
unless block
raise ArgumentError, "A Block must be supplied in order to be watched"
end
@callback = block
unless glob
raise ArgumentErrorn, "A glob must be supplied in order to be watched"
end
@glob = glob
if Pathname.new(glob).absolute?
@full_glob = glob
else
@full_glob = File.join(Compass.configuration.project_path, glob)
end
end
def run_callback(base, relative, action)
callback.call(base, relative, action)
end
def run_once_per_changeset?
false
end
def match?(changed_path)
File.fnmatch(full_glob, changed_path, File::FNM_PATHNAME)
end
end
end
end
================================================
FILE: core/lib/compass/configuration.rb
================================================
module Compass
module Configuration
class << self
def attributes_for_directory(dir_name, http_dir_name = dir_name)
[
"#{dir_name}_dir",
"#{dir_name}_path",
("http_#{http_dir_name}_dir" if http_dir_name),
("http_#{http_dir_name}_path" if http_dir_name)
].compact.map{|a| a.to_sym}
end
# Registers a new configuration property.
# Extensions can use this to add new configuration options to compass.
#
# @param [Symbol] name The name of the property.
# @param [String] comment A comment for the property.
# @param [Proc] default A method to calculate the default value for the property.
# The proc is executed in the context of the project's configuration data.
def add_configuration_property(name, comment = nil, &default)
ATTRIBUTES << name
if comment.is_a?(String)
unless comment[0..0] == "#"
comment = "# #{comment}"
end
unless comment[-1..-1] == "\n"
comment = comment + "\n"
end
Data.class_eval <<-COMMENT
def comment_for_#{name}
#{comment.inspect}
end
COMMENT
end
Data.send(:define_method, :"default_#{name}", &default) if default
Data.inherited_accessor(name)
if name.to_s =~ /dir|path/
Data.strip_trailing_separator(name)
end
end
# For testing purposes
def remove_configuration_property(name)
ATTRIBUTES.delete(name)
end
end
ATTRIBUTES = [
# What kind of project?
:project_type,
# Where is the project?
:project_path,
:http_path,
# Where are the various bits of the project
attributes_for_directory(:css, :stylesheets),
attributes_for_directory(:sass, nil),
attributes_for_directory(:images),
attributes_for_directory(:generated_images),
attributes_for_directory(:javascripts),
attributes_for_directory(:fonts),
attributes_for_directory(:extensions, nil),
# Compilation options
:output_style,
:sourcemap,
:environment,
:relative_assets,
:sass_options,
attributes_for_directory(:cache, nil),
:cache,
# Helper configuration
:asset_host,
:asset_cache_buster,
:line_comments,
:color_output,
:preferred_syntax,
:disable_warnings,
:sprite_engine,
:chunky_png_options
].flatten
ARRAY_ATTRIBUTES = [
:additional_import_paths,
:sprite_load_path,
:required_libraries,
:loaded_frameworks,
:framework_path
]
ARRAY_ATTRIBUTE_OPTIONS = {
:sprite_load_path => { :clobbers => true }
}
RUNTIME_READONLY_ATTRIBUTES = [
:cache,
attributes_for_directory(:cache, nil),
:chunky_png_options,
:color_output,
attributes_for_directory(:css, :stylesheets),
:environment,
attributes_for_directory(:extensions, nil),
:framework_path,
attributes_for_directory(:javascripts),
:line_comments,
:loaded_frameworks,
:output_style,
:preferred_syntax,
:project_path,
:project_type,
:required_libraries,
attributes_for_directory(:sass, nil),
:sass_options,
:sourcemap,
:sprite_engine,
].flatten
end
class << self
# The Compass configuration singleton.
def configuration
@configuration ||= default_configuration
if block_given?
yield @configuration
end
@configuration
end
def default_configuration
Compass::Configuration::Data.new('defaults').extend(Compass::Configuration::Defaults)
end
def add_configuration(data, filename = nil)
return if data.nil?
unless data.is_a?(Compass::Configuration::Data)
# XXX HAX Need to properly factor this apart from the main compass project
if respond_to?(:configuration_for)
data = configuration_for(data, filename)
else
raise ArgumentError, "Invalid argument: #{data.inspect}"
end
end
data.inherit_from!(configuration) if configuration
data.on_top!
@configuration = data
end
def reset_configuration!
@configuration = nil
end
# Returns a full path to the relative path to the project directory
def projectize(path, project_path = nil)
project_path ||= configuration.project_path
File.join(project_path, *path.split('/'))
end
def deprojectize(path, project_path = nil)
project_path ||= configuration.project_path
if path[0..(project_path.size - 1)] == project_path
path[(project_path.size + 1)..-1]
else
path
end
end
end
end
%w(defaults inheritance paths data watch adapters).each do |lib|
require "compass/configuration/#{lib}"
end
================================================
FILE: core/lib/compass/core/caniuse.rb
================================================
require 'multi_json'
require 'singleton'
class Compass::Core::CanIUse
include Singleton
DATA_FILE_NAME = File.join(Compass::Core.base_directory, "data", "caniuse.json")
DATA_FEATURE_FILES = Dir.glob(File.join(Compass::Core.base_directory, "data", "caniuse_extras", "**", "*.json"))
def initialize
@data = MultiJson.load(File.read(DATA_FILE_NAME))
# support ad-hoc features
DATA_FEATURE_FILES.each do |feature_file|
feature_name = File.basename(feature_file, ".json")
# if the feature doesn't exist in the master `caniuse.json`
if @data["data"][feature_name].nil?
@data["data"][feature_name] = MultiJson.load(File.read(feature_file))
end
end
end
# The browser names from caniuse are ugly.
PUBLIC_BROWSER_NAMES = Hash.new {|h, k| k}
PUBLIC_BROWSER_NAMES.update(
"and_chr" => "android-chrome",
"and_ff" => "android-firefox",
"android" => "android",
"bb" => "blackberry",
"chrome" => "chrome",
"firefox" => "firefox",
"ie" => "ie",
"ie_mob" => "ie-mobile",
"ios_saf" => "ios-safari",
"op_mini" => "opera-mini",
"op_mob" => "opera-mobile",
"opera" => "opera",
"safari" => "safari"
)
CAN_I_USE_NAMES = Hash.new {|h, k| k}
CAN_I_USE_NAMES.update(PUBLIC_BROWSER_NAMES.invert)
# Returns all the known browsers according to caniuse
def browsers
@browsers ||= @data["agents"].keys.map{|b| PUBLIC_BROWSER_NAMES[b] }.sort
end
# Returns the prefix corresponding to a particular browser
def prefix(browser, version = nil)
version = caniuse_version(browser, version)
assert_valid_browser browser
assert_valid_version browser, version if version
data = browser_data(browser)
p = if data["prefix_exceptions"] && data["prefix_exceptions"][version]
data["prefix_exceptions"][version]
else
data["prefix"]
end
"-#{p}"
end
# returns all possible prefixes a browser might use.
def all_prefixes(browser)
assert_valid_browser browser
data = browser_data(browser)
prefixes = ["-#{data["prefix"]}"]
if data["prefix_exceptions"]
prefixes += data["prefix_exceptions"].values.uniq.map{|p| "-#{p}"}
end
prefixes
end
# returns the prefixes needed by the list of browsers given
def prefixes(browsers = browsers())
result = browsers.map{|b| all_prefixes(b) }
result.flatten!
result.uniq!
result.sort!
result
end
def browser_ranges(capability, prefix = nil, include_unprefixed_versions = true)
assert_valid_capability capability
browsers = prefix.nil? ? browsers() : browsers_with_prefix(prefix)
browsers.inject({}) do |m, browser|
browser_versions = versions(browser)
min_version = find_first_prefixed_version(browser, browser_versions, capability, prefix)
if min_version
max_version = if include_unprefixed_versions
browser_versions.last
else
find_first_prefixed_version(browser, browser_versions.reverse, capability, prefix)
end
m.update(browser => [min_version, max_version])
end
m
end
end
def find_first_prefixed_version(browser, versions, capability, prefix)
versions.find do |version|
support = browser_support(browser, version, capability)
if prefix.nil?
support !~ /\b(n|p)\b/ && support !~ /\bx\b/
else
actual_prefix = prefix(browser, version)
support !~ /\b(n|p)\b/ && support =~ /\bx\b/ && prefix == actual_prefix
end
end
end
# @overload omitted_usage(browser, min_supported_version)
# How many users would be omitted if support for the given browser starts
# with the given version.
#
# @overload omitted_usage(browser, min_unsupported_version, max_unsupported_version)
# How many users would be omitted if the browsers with version
def omitted_usage(browser, min_version, max_version = nil)
versions = versions(browser)
min_version = caniuse_version(browser, min_version)
max_version = caniuse_version(browser, max_version)
if max_version.nil?
assert_valid_version browser, min_version
else
assert_valid_version browser, min_version, max_version
end
usage = 0
in_range = max_version.nil?
versions.each do |version|
break if max_version.nil? && version == min_version
in_range = true if (!max_version.nil? && version == min_version)
usage += usage(browser, version) if in_range
break if !max_version.nil? && version == max_version
end
return usage
end
# returns the list of browsers that use the given prefix
def browsers_with_prefix(prefix)
assert_valid_prefix prefix
prefix = "-" + prefix unless prefix.start_with?("-")
browsers.select {|b| all_prefixes(b).include?(prefix) }
end
SPEC_VERSION_MATCHERS = Hash.new do |h, k|
h[k] = /##{k}\b/
end
CAPABILITY_MATCHERS = {
:full_support => lambda {|support, capability| !support ^ (capability =~ /\by\b/) },
:partial_support => lambda {|support, capability| !support ^ (capability =~ /\ba\b/) },
:prefixed => lambda {|support, capability| !support ^ (capability =~ /\bx\b/) },
:spec_versions => lambda {|versions, capability| versions.any? {|v| capability =~ SPEC_VERSION_MATCHERS[v] } }
}
# Return whether the capability matcher the options specified.
# For each capability option in the options the capability will need to match it.
def capability_matches(support, capability_options_list)
capability_options_list.any? do |capability_options|
capability_options.all? {|c, v| CAPABILITY_MATCHERS[c].call(v, support)}
end
end
# returns the percentage of users (0-100) that would be affected if the prefix
# was not used with the given capability.
def prefixed_usage(prefix, capability, capability_options_list)
assert_valid_prefix prefix
assert_valid_capability capability
usage = 0
browsers_with_prefix(prefix).each do |browser|
versions(browser).each do |version|
next unless prefix == prefix(browser, version)
support = browser_support(browser, version, capability)
if capability_matches(support, capability_options_list) and support =~ /\bx\b/
usage += usage(browser, version)
end
end
end
usage
end
def next_version(browser, version)
version = caniuse_version(browser, version)
versions = versions(browser)
index = versions.index(version)
index < versions.length - 1 ? versions[index + 1] : nil
end
def previous_version(browser, version)
version = caniuse_version(browser, version)
versions = versions(browser)
index = versions.index(version)
index > 0 ? versions[index - 1] : nil
end
# Returns whether the given minimum version of a browser
# requires the use of a prefix for the stated capability.
def requires_prefix(browser, min_version, capability, capability_options_list)
min_version = caniuse_version(browser, min_version)
assert_valid_browser browser
assert_valid_capability capability
found_version = false
versions(browser).each do |version|
found_version ||= version == min_version
next unless found_version
support = browser_support(browser, version, capability)
if capability_matches(support, capability_options_list) and support =~ /\bx\b/
return prefix(browser, version)
end
end
raise ArgumentError, "#{min_version} is not a version for #{browser}" unless found_version
nil
end
# These are versions that users might reasonably type
# mapped to the caniuse version.
ALTERNATE_VERSIONS = {
"android" => {
"4.2" => "4.2-4.3",
"4.3" => "4.2-4.3"
},
"opera" => {
"9.5" => "9.5-9.6",
"9.6" => "9.5-9.6",
"10.0" => "10.0-10.1",
"10.1" => "10.0-10.1",
},
"opera-mobile" => {
"14" => "0"
}
}
# Returns the versions of a browser. If the min_usage parameter is provided,
# only those versions having met the threshold of user percentage.
#
# @param min_usage a decimal number betwee 0 and 100
def versions(browser, min_usage = 0)
assert_valid_browser browser
versions = browser_data(browser)["versions"].compact
return versions if min_usage == 0
versions.select {|v| browser_data(browser)["usage_global"][v] > min_usage }
end
# The list of capabilities tracked by caniuse.
def capabilities
@capabilities ||= @data["data"].keys.select do |cap|
cats = @data["data"][cap]["categories"]
cats.any?{|cat| cat =~ /CSS/ }
end.sort
end
# the usage % for a given browser version.
def usage(browser, version)
browser_data(browser)["usage_global"][version]
end
# returns a valid version given the version provided by the user
# This is used to maintain API compatibility when caniuse removes
# a version from their data (which seems to be replaced with a semantic equivalent).
def caniuse_version(browser, version)
return unless version
ALTERNATE_VERSIONS[browser] && ALTERNATE_VERSIONS[browser][version] || version
end
def inspect
"#{self.class.name}(#{browsers.join(", ")})"
end
# the browser data assocated with a given capability
def capability_data(capability)
@data["data"][capability]
end
def browser_support(browser, version, capability)
version = caniuse_version(browser, version)
capability_data(capability)["stats"][CAN_I_USE_NAMES[browser]][version]
end
# the metadata assocated with a given browser
def browser_data(browser)
@data["agents"][CAN_I_USE_NAMES[browser]]
end
# efficiently checks if a prefix is valid
def assert_valid_prefix(prefix)
@known_prefixes ||= Set.new(prefixes(browsers))
unless @known_prefixes.include?(prefix)
raise ArgumentError, "#{prefix} is not known browser prefix."
end
end
# efficiently checks if a browser is valid
def assert_valid_browser(browser)
@known_browsers ||= Set.new(browsers)
unless @known_browsers.include?(browser)
raise ArgumentError, "#{browser} is not known browser."
end
end
# efficiently checks if a capability is valid
def assert_valid_capability(capability)
@known_capabilities ||= Set.new(capabilities)
unless @known_capabilities.include?(capability)
raise ArgumentError, "#{capability} is not known browser capability."
end
nil
end
def assert_valid_version(browser, *versions)
versions.each do |v|
unless versions(browser).include?(v)
raise ArgumentError, "#{v} is not known version for #{browser}."
end
end
end
end
================================================
FILE: core/lib/compass/core/generated_version.rb
================================================
module Compass
module Core
# This file intentionally does nothing.
# The build process will generate a VERSION constant here.
end
end
================================================
FILE: core/lib/compass/core/sass_extensions/functions/colors.rb
================================================
module Compass::Core::SassExtensions::Functions::Colors
# a genericized version of lighten/darken so that negative values can be used.
def adjust_lightness(color, amount)
assert_type color, :Color
assert_type amount, :Number
color.with(:lightness => Sass::Util.restrict(color.lightness + amount.value, 0..100))
end
# Scales a color's lightness by some percentage.
# If the amount is negative, the color is scaled darker, if positive, it is scaled lighter.
# This will never return a pure light or dark color unless the amount is 100%.
def scale_lightness(color, amount)
assert_type color, :Color
assert_type amount, :Number
color.with(:lightness => scale_color_value(color.lightness, amount.value))
end
# a genericized version of saturation/desaturate so that negative values can be used.
def adjust_saturation(color, amount)
assert_type color, :Color
assert_type amount, :Number
color.with(:saturation => Sass::Util.restrict(color.saturation + amount.value, 0..100))
end
# Scales a color's saturation by some percentage.
# If the amount is negative, the color is desaturated, if positive, it is saturated.
# This will never return a pure saturated or desaturated color unless the amount is 100%.
def scale_saturation(color, amount)
assert_type color, :Color
assert_type amount, :Number
color.with(:saturation => scale_color_value(color.saturation, amount.value))
end
def shade(color, percentage)
assert_type color, :Color
assert_type percentage, :Number
black = rgb_color(0, 0, 0)
mix(black, color, percentage)
end
def tint(color, percentage)
assert_type color, :Color
assert_type percentage, :Number
white = rgb_color(255, 255, 255)
mix(white, color, percentage)
end
# returns an IE hex string for a color with an alpha channel
# suitable for passing to IE filters.
def ie_hex_str(color)
assert_type color, :Color
alpha = (color.alpha * 255).round
alphastr = alpha.to_s(16).rjust(2, '0')
identifier("##{alphastr}#{color.send(:hex_str)[1..-1]}".upcase)
end
private
def scale_color_value(value, amount)
if amount > 0
value += (100 - value) * (amount / 100.0)
elsif amount < 0
value += value * amount / 100.0
end
value
end
end
================================================
FILE: core/lib/compass/core/sass_extensions/functions/configuration.rb
================================================
require 'pathname'
module Compass::Core::SassExtensions::Functions::Configuration
extend Compass::Core::SassExtensions::Functions::SassDeclarationHelper
# Users who need to support windows and unix paths in their configuration
# should construct them with this helper function.
def join_file_segments(*segments)
quoted_string(File.join(*segments.map{|s| assert_type s, :String; s.value}))
end
declare :absolute_path, [], :var_args => true
# Returns an absolute path for the path relative to the sass file it was called from.
def absolute_path(relative_path)
quoted_string(File.expand_path(File.join(File.dirname(options[:filename]), relative_path.value)))
end
declare :absolute_path, [:relative_path]
# split a file into directory, basename, and extension
def split_filename(path)
pathname = Pathname.new(path.value)
list(quoted_string(pathname.dirname.to_s),
quoted_string(pathname.basename(pathname.extname).to_s),
quoted_string(pathname.extname.to_s),
:space)
end
declare :split_filename, [:path]
# Returns true if the compass compiler is compiling this stylesheet.
def using_compass_compiler
bool(options[:compass] && options[:compass][:compiler_in_use])
end
declare :using_compass_compiler, []
def reset_configuration()
Compass.reset_configuration!
null()
end
declare :reset_configuration, []
def add_sass_configuration(project_path)
css_location = template_location = nil
if options[:template_location] && options[:template_location].is_a?(Array)
css_location = File.expand_path(options[:template_location].first.last)
template_location = File.expand_path(options[:template_location].first.first)
else
css_location = File.expand_path(options[:css_location]) if options[:css_location]
template_location = File.expand_path(options[:template_location]) if options[:template_location]
end
original_filename = File.expand_path(options[:original_filename]) if options[:original_filename]
project_path = if project_path.value.nil?
if css_location && template_location
common_parent_directory(css_location, template_location)
end
else
project_path.value
end
config = {
:project_path => project_path,
:cache => options[:cache],
:additional_import_paths => options[:load_paths],
:line_comments => options[:line_comments]
}
unless options[:quiet].nil?
config.update(:disable_warnings => options[:quiet])
end
if project_path && css_location && (css_dir = relative_path_from(css_location, project_path))
config.update(:css_dir => css_dir)
elsif css_location
config.update(:css_path => css_location)
end
if project_path && template_location && (sass_dir = relative_path_from(template_location, project_path))
config.update(:sass_dir => sass_dir)
elsif template_location
config.update(:css_path => template_location)
end
config_name = "Sass Defaults: #{project_path ? relative_path_from(original_filename, project_path) : original_filename}"
Compass.add_configuration(Compass::Configuration::Data.new(config_name, config))
update_sass_options!
null
rescue => e
puts e.backtrace.join("\n")
raise
end
declare :add_sass_configuration, [:project_path]
OPTION_TRANSFORMER = Hash.new() {|h, k| proc {|v, ctx| v.value } }
OPTION_TRANSFORMER[:asset_cache_buster] = proc do |v, ctx|
proc do |url, file|
if ctx.environment.function(v.value) || Sass::Script::Functions.callable?(v.value.tr('-', '_'))
result = ctx.call(v, ctx.quoted_string(url),
file.nil? ? ctx.null() : ctx.quoted_string(file.path))
case result
when Sass::Script::Value::String, Sass::Script::Value::Null
result.value
else
ctx.assert_type(result, :Map)
result.value.keys.inject({}) do |r, k|
ctx.assert_type k, :String
ctx.assert_type(result.value[k], :String) unless result.value[k].value.nil?
if k.value == "path" || k.value == "query"
r[k.value.to_sym] = result.value[k].value
end
r
end
end
else
raise ArgumentError, "#{v.value} is not a function."
end
end
end
OPTION_TRANSFORMER[:asset_host] = proc do |v, ctx|
proc do |file|
if ctx.environment.function(v.value) || Sass::Script::Functions.callable?(v.value.tr('-', '_'))
result = ctx.call(v, ctx.quoted_string(file))
case result
when Sass::Script::Value::String, Sass::Script::Value::Null
result.value
else
ctx.assert_type(result, :String)
end
else
raise ArgumentError, "#{v.value} is not a function."
end
end
end
def add_configuration(options)
attributes = {}
options.value.keys.each do |key|
underscored = key.value.to_s.tr("-", "_")
unless runtime_writable_attributes.find{|a| a.to_s == underscored}
raise ArgumentError, "#{key} is not a valid configuration option."
end
underscored = underscored.to_sym
attributes[underscored] = OPTION_TRANSFORMER[underscored].call(options.value[key], self)
end
name = "#{options.source_range.file}:#{options.source_range.start_pos.line}"
Compass.add_configuration(Compass::Configuration::Data.new(name, attributes))
update_sass_options!
null
end
declare :add_configuration, [:options]
private
def runtime_writable_attributes
Compass::Configuration::ATTRIBUTES - Compass::Configuration::RUNTIME_READONLY_ATTRIBUTES
end
def common_parent_directory(directory1, directory2)
relative = Pathname.new(directory1).relative_path_from(Pathname.new(directory2))
File.expand_path(directory2, relative.to_s.scan("..#{File::SEPARATOR}").join)
end
def relative_path_from(directory1, directory2)
Pathname.new(directory1).relative_path_from(Pathname.new(directory2)).to_s
end
def update_sass_options!
Compass.configuration.additional_import_paths.each do |lp|
options[:load_paths] << lp unless options[:load_paths].include?(lp)
end
if Compass.configuration.disable_warnings
Sass.logger.log_level = :error
else
Sass.logger.log_level = :warn
end
end
end
================================================
FILE: core/lib/compass/core/sass_extensions/functions/constants.rb
================================================
module Compass::Core::SassExtensions::Functions::Constants
POSITIONS = /top|bottom|left|right|center/
def is_position(position)
bool(position.is_a?(Sass::Script::Value::String) && !!(position.value =~ POSITIONS))
end
def is_position_list(position_list)
bool(position_list.is_a?(Sass::Script::Value::List) && position_list.value.all?{|p| is_position(p).to_bool})
end
# returns the opposite position of a side or corner.
def opposite_position(position)
position = unless position.is_a?(Sass::Script::Value::List)
list(position, :space)
else
list(position.value.dup, position.separator)
end
position = list(position.value.map do |pos|
if pos.is_a? Sass::Script::Value::String
opposite = case pos.value
when "top" then "bottom"
when "bottom" then "top"
when "left" then "right"
when "right" then "left"
when "center" then "center"
else
Compass::Util.compass_warn("Cannot determine the opposite position of: #{pos}")
pos.value
end
identifier(opposite)
elsif pos.is_a? Sass::Script::Value::Number
if pos.numerator_units == ["%"] && pos.denominator_units == []
number(100-pos.value, "%")
else
Compass::Util.compass_warn("Cannot determine the opposite position of: #{pos}")
pos
end
else
Compass::Util.compass_warn("Cannot determine the opposite position of: #{pos}")
pos
end
end, position.separator)
if position.value.size == 1
position.value.first
else
position
end
end
def is_url(string)
if string.is_a?(Sass::Script::Value::String)
is_url = !!(string.value =~ /^url\(.*\)$/)
bool(is_url)
else
bool(false)
end
end
end
================================================
FILE: core/lib/compass/core/sass_extensions/functions/cross_browser_support.rb
================================================
module Compass::Core::SassExtensions::Functions::CrossBrowserSupport
extend Compass::Core::SassExtensions::Functions::SassDeclarationHelper
class CSS2FallbackValue < Sass::Script::Value::Base
attr_accessor :value, :css2_value
def children
[value, css2_value]
end
def initialize(value, css2_value)
self.value = value
self.css2_value = css2_value
end
def inspect
to_s
end
def to_s(options = self.options)
value.to_s(options)
end
def supports?(aspect)
aspect == "css2"
end
def has_aspect?
true
end
def to_css2(options = self.options)
css2_value
end
end
# Check if any of the arguments passed require a vendor prefix.
def prefixed(prefix, *args)
assert_type prefix, :String
aspect = prefix.value.sub(/^-/,"")
needed = args.any?{|a| a.respond_to?(:supports?) && a.supports?(aspect)}
bool(needed)
end
%w(webkit moz o ms svg css2 owg).each do |prefix|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
# Syntactic sugar to apply the given prefix
# -moz($arg) is the same as calling prefix(-moz, $arg)
def _#{prefix}(*args)
prefix("#{prefix}", *args)
end
RUBY
end
def prefix(prefix, *objects)
assert_type prefix, :String if prefix.is_a?(Sass::Script::Value::Base)
prefix = prefix.value if prefix.is_a?(Sass::Script::Value::String)
prefix = prefix[1..-1] if prefix[0] == ?-
if objects.size > 1
self.prefix(prefix, list(objects, :comma))
else
object = objects.first
if object.is_a?(Sass::Script::Value::List)
list(object.value.map{|e|
self.prefix(prefix, e)
}, object.separator)
elsif object.respond_to?(:supports?) && object.supports?(prefix) && object.respond_to?(:"to_#{prefix}")
object.options = options
object.send(:"to_#{prefix}")
else
object
end
end
end
def css2_fallback(value, css2_value)
CSS2FallbackValue.new(value, css2_value)
end
# The known browsers.
#
# If prefix is given, limits the returned browsers to those using the specified prefix.
def browsers(prefix = nil)
browsers = if prefix
assert_type prefix, :String
Compass::Core::CanIUse.instance.browsers_with_prefix(prefix.value)
else
Compass::Core::CanIUse.instance.browsers
end
list(browsers.map{|b| identifier(b)}, :comma)
end
declare(:browsers, [])
declare(:browsers, [:prefix])
# The known capabilities of browsers.
def browser_capabilities
list(Compass::Core::CanIUse.instance.capabilities.map{|c| identifier(c)}, :comma)
end
declare(:browser_capabilities, [])
# The versions for the given browser.
def browser_versions(browser)
assert_type browser, :String
list(Compass::Core::CanIUse.instance.versions(browser.value).map{|v| quoted_string(v)}, :comma)
rescue ArgumentError => e
raise Sass::SyntaxError.new(e.message)
end
declare(:browser_versions, [:browser])
# whether the browser uses a prefix for the given capability at the version
# specified or a later version. Returns the prefix it requires, or null.
def browser_requires_prefix(browser, version, capability, capability_options)
assert_type browser, :String
assert_type version, :String
assert_type capability, :String
p = Compass::Core::CanIUse.instance.requires_prefix(browser.value,
version.value,
capability.value,
unbox_capability_options_list(capability_options))
p ? identifier(p) : null()
rescue ArgumentError => e
raise Sass::SyntaxError.new(e.message)
end
declare(:browser_requires_prefix, [:browser, :version, :capability])
# the prefix for the given browser.
def browser_prefix(browser, version = nil)
assert_type browser, :String
identifier(Compass::Core::CanIUse.instance.prefix(browser.value))
rescue ArgumentError => e
raise Sass::SyntaxError.new(e.message)
end
declare(:browser_prefix, [:browser])
declare(:browser_prefix, [:browser, :version])
# The prefixes used by the given browsers.
def browser_prefixes(browsers)
browsers = list(browsers, :comma) if browsers.is_a?(Sass::Script::Value::String)
assert_type browsers, :List
browser_strings = browsers.value.map {|b| assert_type(b, :String); b.value }
prefix_strings = Compass::Core::CanIUse.instance.prefixes(browser_strings)
list(prefix_strings.map {|p| identifier(p)}, :comma)
rescue ArgumentError => e
raise Sass::SyntaxError.new(e.message)
end
declare(:browser_prefixes, [:browsers])
# The percent of users that are omitted by setting the min_version of browser
# as specified.
def omitted_usage(browser, min_version, max_version = nil)
assert_type browser, :String
assert_type min_version, :String, :min_version
assert_type(max_version, :String, :max_version) if max_version
versions = [min_version.value]
versions << max_version.value if max_version
number(Compass::Core::CanIUse.instance.omitted_usage(browser.value, *versions))
end
declare(:omitted_usage, [:browser, :min_version])
declare(:omitted_usage, [:browser, :min_version, :max_version])
# The version before the version for the browser specified
def previous_version(browser, version)
assert_type browser, :String
assert_type version, :String
previous = Compass::Core::CanIUse.instance.previous_version(browser.value, version.value)
previous.nil? ? null() : quoted_string(previous)
end
declare(:previous_version, [:browser, :version])
# The version before the version for the browser specified
def next_version(browser, version)
assert_type browser, :String
assert_type version, :String
next_version = Compass::Core::CanIUse.instance.next_version(browser.value, version.value)
next_version.nil? ? null() : quoted_string(next_version)
end
declare(:next_version, [:browser, :version])
# The percent of users relying on a particular prefix
def prefix_usage(prefix, capability, capability_options)
assert_type prefix, :String
assert_type capability, :String
number(Compass::Core::CanIUse.instance.prefixed_usage(prefix.value,
capability.value,
unbox_capability_options_list(capability_options)))
rescue ArgumentError => e
raise Sass::SyntaxError.new(e.message)
end
declare(:prefix_usage, [:prefix, :capability])
# Compares two browser versions. Returning:
#
# * 0 if they are the same
# * <0 if the first version is less than the second
# * >0 if the first version is more than the second
def compare_browser_versions(browser, version1, version2)
assert_type browser, :String, :browser
assert_type version1, :String, :version1
assert_type version2, :String, :version2
index1 = index2 = nil
Compass::Core::CanIUse.instance.versions(browser.value).each_with_index do |v, i|
index1 = i if v == version1.value
index2 = i if v == version2.value
break if index1 && index2
end
unless index1
raise Sass::SyntaxError.new("#{version1} is not a version for #{browser}")
end
unless index2
raise Sass::SyntaxError.new("#{version2} is not a version for #{browser}")
end
number(index1 <=> index2)
end
declare(:compare_browser_versions, [:browser, :version1, :version2])
# Returns a map of browsers to the first version the capability became available
# without a prefix.
#
# If a prefix is provided, only those browsers using that prefix will be returned
# and the minimum version will be when it first became available as a prefix or
# without a prefix.
#
# If a browser does not have the capability, it will not included in the map.
def browser_ranges(capability, prefix = null(), include_unprefixed_versions = bool(true))
assert_type capability, :String
assert_type(prefix, :String) unless prefix == null()
mins = Compass::Core::CanIUse.instance.browser_ranges(capability.value,
prefix.value,
include_unprefixed_versions.to_bool)
Sass::Script::Value::Map.new(mins.inject({}) do |m, (h, range)|
m[identifier(h)] = list(range.map{|version| quoted_string(version)}, :space)
m
end)
end
declare(:browser_minimums, [:capability])
declare(:browser_minimums, [:capability, :prefix])
private
def unbox_capability_options_list(capability_options_list)
if capability_options_list.is_a?(Sass::Script::Value::Map)
[unbox_capability_options(capability_options_list)]
elsif capability_options_list.is_a?(Sass::Script::Value::List)
capability_options_list.to_a.map{|opts| unbox_capability_options(opts) }
else
assert_type capability_options_list, :List
end
end
CAPABILITY_OPTION_KEYS = {
"full-support" => :full_support,
"partial-support" => :partial_support,
"prefixed" => :prefixed,
"spec-versions" => :spec_versions,
}
CAPABILITY_OPTION_UNBOXER = {
:full_support => lambda {|v| v.to_bool },
:partial_support => lambda {|v| v.to_bool },
:prefixed => lambda {|v| v.to_bool },
:spec_versions => lambda {|versions| versions.to_a.map {|v| v.value } }
}
def unbox_capability_options(capability_options)
assert_type capability_options, :Map
result = {}
capability_options.value.each do |k, v|
assert_type k, :String
key = CAPABILITY_OPTION_KEYS[k.value]
unless key
raise Sass::SyntaxError, "#{k} is not valid capability option"
end
result[key] = CAPABILITY_OPTION_UNBOXER[key].call(v)
end
result
end
end
================================================
FILE: core/lib/compass/core/sass_extensions/functions/display.rb
================================================
module Compass::Core::SassExtensions::Functions::Display
DEFAULT_DISPLAY = {
"block" => %w{address article aside blockquote center dir div dd details dl dt fieldset
figcaption figure form footer frameset h1 h2 h3 h4 h5 h6 hr header hgroup
isindex main menu nav noframes noscript ol p pre section summary ul},
"inline" => %w{a abbr acronym audio b basefont bdo big br canvas cite code command
datalist dfn em embed font i img input keygen kbd label mark meter output
progress q rp rt ruby s samp select small span strike strong sub
sup textarea time tt u var video wbr},
"inline-block" => %w{img},
"table" => %w{table},
"list-item" => %w{li},
"table-row-group" => %w{tbody},
"table-header-group" => %w{thead},
"table-footer-group" => %w{tfoot},
"table-row" => %w{tr},
"table-cell" => %w{th td},
"html5-block" => %w{article aside details figcaption figure footer header hgroup main menu nav
section summary},
"html5-inline" => %w{audio canvas command datalist embed keygen mark meter output progress rp
rt ruby time video wbr},
"text-input" => %w{input textarea}
}
DEFAULT_DISPLAY["html5"] = (DEFAULT_DISPLAY["html5-block"] + DEFAULT_DISPLAY["html5-inline"]).sort.uniq
# returns a comma delimited string for all the
# elements according to their default css3 display value.
def elements_of_type(display)
identifier(DEFAULT_DISPLAY.fetch(display.value.to_s).join(", "))
end
end
================================================
FILE: core/lib/compass/core/sass_extensions/functions/enumerate.rb
================================================
module Compass::Core::SassExtensions::Functions::Enumerate
def enumerate(prefix, from, through, separator = nil)
separator ||= identifier("-")
selectors = (from.value..through.value).map{|i| "#{prefix.value}#{separator.value}#{i}"}.join(", ")
identifier(selectors)
end
end
================================================
FILE: core/lib/compass/core/sass_extensions/functions/env.rb
================================================
module Compass::Core::SassExtensions::Functions::Env
extend Compass::Core::SassExtensions::Functions::SassDeclarationHelper
extend Sass::Script::Value::Helpers
def compass_env
compass_opts = options[:compass] || {}
identifier((compass_opts[:environment] || "development").to_s)
end
declare :compass_env, []
DEFAULT_TIME = identifier("%T%:z")
def current_time(format = DEFAULT_TIME)
assert_type format, :String
identifier(Time.now.strftime(format.value))
end
declare :current_time, []
declare :current_time, [:format]
DEFAULT_DATE = identifier("%F")
def current_date(format = DEFAULT_DATE)
current_time(format)
end
declare :current_date, []
declare :current_date, [:format]
NOT_ABSOLUTE = bool(false)
def current_source_file(absolute = NOT_ABSOLUTE)
if absolute.to_bool
identifier(options[:original_filename].to_s)
else
filename = Pathname.new(options[:original_filename].to_s)
sass_path = Pathname.new(Compass.configuration.sass_path)
relative_filename = filename.relative_path_from(sass_path).to_s rescue filename
identifier(relative_filename.to_s)
end
end
declare :current_source_file, []
declare :current_source_file, [:absolute]
def current_output_file(absolute = NOT_ABSOLUTE)
if absolute.to_bool
identifier(options[:css_filename].to_s)
else
filename = Pathname.new(options[:css_filename].to_s)
css_path = Pathname.new(Compass.configuration.css_path)
relative_filename = filename.relative_path_from(css_path).to_s rescue filename
identifier(relative_filename.to_s)
end
end
declare :current_output_file, []
declare :current_output_file, [:absolute]
def compass_extensions
exts = Sass::Util.ordered_hash(identifier("compass") => quoted_string(Compass::Core::VERSION))
if defined?(Compass::Frameworks::ALL)
Compass::Frameworks::ALL.each do |framework|
next if framework.name == "compass"
exts[identifier(framework.name)] =
framework.version ? quoted_string(framework.version) : bool(true);
end
end
map(exts)
end
declare :compass_extensions, []
def at_stylesheet_root
bool(environment.selector.nil?)
end
declare :at_stylesheet_root, []
end
================================================
FILE: core/lib/compass/core/sass_extensions/functions/files.rb
================================================
require 'digest/md5'
module Compass::Core::SassExtensions::Functions::Files
extend Compass::Core::SassExtensions::Functions::SassDeclarationHelper
extend Sass::Script::Value::Helpers
def md5sum(file, format = nil)
assert_type file, :String
filename = nil
if options[:css_filename] && File.exists?(options[:css_filename])
filename = File.expand_path(file.value, File.dirname(options[:css_filename]))
elsif Pathname.new(file.value).absolute?
filename = file.value
end
if filename && File.exist?(filename)
assert_type file, :String if format
digest = Digest::MD5.new()
digest << File.read(filename)
if !format || format.value == "hex"
unquoted_string(digest.hexdigest)
elsif format && format.value == "integer"
number(digest.hexdigest.hex)
elsif format
raise Sass::SyntaxError, "Unknown format '#{format}' for md5sum"
end
else
raise Sass::SyntaxError, "File not found: #{file}"
end
end
declare :md5sum, [:file]
declare :md5sum, [:file, :format]
end
================================================
FILE: core/lib/compass/core/sass_extensions/functions/font_files.rb
================================================
module Compass::Core::SassExtensions::Functions::FontFiles
FONT_TYPES = {
:woff => 'woff',
:woff2 => 'woff2',
:otf => 'opentype',
:opentype => 'opentype',
:ttf => 'truetype',
:truetype => 'truetype',
:svg => 'svg',
:eot => 'embedded-opentype'
}
def font_formats(*args)
formats = []
with_each_font_file(*args) do |path, type|
formats << identifier(type)
end
return list(formats, :comma)
end
def font_files(*args)
return null unless args.any?
files = []
with_each_font_file(*args) do |path, type|
files << list(font_url(path), identifier("format('#{type}')"), :space)
end
list(files, :comma)
end
protected
def with_each_font_file(*args)
skip_next = false
args.each_with_index do |path, index|
assert_type path, :String
path = unquote(path)
# if we were told to skip this iteration, do so...
if skip_next
skip_next = false
next
end
# back-compat support for passing the font type e.g.
# font-files('path/to/file.ttf', truetype, 'path/to/file.otf', opentype);
type = args[index + 1]
type = type.nil? ? :wrong : type.value.to_sym
# if the type is valid, keep it, and skip the next index (as it was the type)
if FONT_TYPES.key? type
skip_next = true
# otherwise, we need to look at the file extension to derive the type...
else
# let pass url like font.type?thing#stuff
type = path.to_s.split('.').last.gsub(/(\?(.*))?(#(.*))?\"?/, '').to_sym
end
if FONT_TYPES.key? type
yield(path, FONT_TYPES[type]) if block_given?
else
raise Sass::SyntaxError, "Could not determine font type for #{path}"
end
end
end
end
================================================
FILE: core/lib/compass/core/sass_extensions/functions/gradient_support.rb
================================================
module Compass::Core::SassExtensions::Functions::GradientSupport
GRADIENT_ASPECTS = %w(webkit moz svg css2 o owg).freeze
class CSS3AngleToSVGConverter
include Math
def initialize(angle)
@original_angle = angle
@angle = handle_keywords(angle)
@angle = in_radians(@angle) % (2 * PI)
@quadrant = (@angle * 2 / PI).to_i
@angle = case @quadrant
when 0
@angle
when 1
PI - @angle
when 2
@angle - PI
when 3
2 * PI - @angle
end
end
TOP = 1
BOTTOM = 2
RIGHT = 4
LEFT = 8
DIR_KEYWORDS_TO_ANGLE = {
TOP => 0,
TOP | RIGHT => 45,
RIGHT => 90,
BOTTOM | RIGHT => 135,
BOTTOM => 180,
BOTTOM | LEFT => 225,
LEFT => 270,
TOP | LEFT => 315,
}
def handle_keywords(angle)
if angle.is_a?(Sass::Script::Value::List) || angle.is_a?(Sass::Script::Value::String)
direction = angle.to_sass
is_end_point = !!/\bto\b/i.match(direction)
dir = 0
dir |= TOP if /\btop\b/i.match(direction)
dir |= BOTTOM if /\bbottom\b/i.match(direction)
dir |= RIGHT if /\bright\b/i.match(direction)
dir |= LEFT if /\bleft\b/i.match(direction)
if (r = DIR_KEYWORDS_TO_ANGLE[dir])
r += 180 unless is_end_point
Sass::Script::Value::Number.new(r, %w(deg), [])
else
raise Sass::SyntaxError, "Unknown direction: #{angle.to_sass}"
end
else
angle
end
end
def in_radians(angle)
case angle.unit_str
when "deg"
angle.value * PI / 180.0
when "grad"
angle.value * PI / 200.0
when "rad"
angle.value
when "turn"
angle.value * PI * 2
else
raise Sass::SyntaxError.new("#{angle.unit_str} is not an angle")
end
end
def sin2(a)
v = sin(a)
v * v
end
def x
@x ||= if @angle > 1.570621793869697
1.0 # avoid floating point rounding error at the asymptote
else
tan(@angle) + (1 - tan(@angle)) * sin2(@angle)
end
end
def y
@y ||= if @angle < 0.0001
1.0 # the limit of the expression as we approach 0 is 1.
else
x / tan(@angle)
end
end
def x1
result case @quadrant
when 0, 1
-x
when 2, 3
x
end
end
def y1
result case @quadrant
when 0, 3
y
when 1, 2
-y
end
end
def x2
result case @quadrant
when 0, 1
x
when 2, 3
-x
end
end
def y2
result case @quadrant
when 0, 3
-y
when 1, 2
y
end
end
def scale(p)
(p + 1) / 2.0
end
def round6(v)
(v * 1_000_000).round / 1_000_000.0
end
def result(v)
round6(scale(v))
end
end
class ColorStop < Sass::Script::Value::Base
include Sass::Script::Value::Helpers
attr_accessor :color, :stop
def children
[color, stop].compact
end
def initialize(color, stop = nil)
assert_legal_color! color
assert_legal_color_stop! stop if stop
self.color, self.stop = color, stop
end
def inspect
to_s
end
def assert_legal_color!(color)
unless Sass::Script::Value::Color === color ||
Sass::Script::Tree::Funcall === color ||
(Sass::Script::Value::String === color && color.value == "currentColor")||
(Sass::Script::Value::String === color && color.value == "transparent")
raise Sass::SyntaxError, "Expected a color. Got: #{color}"
end
end
def assert_legal_color_stop!(stop)
case stop
when Sass::Script::Value::String
return stop.value.start_with?("calc(")
when Sass::Script::Value::Number
return true
end
raise Sass::SyntaxError, "Expected a number or numerical expression. Got: #{stop.inspect}"
end
def self.color_to_svg_s(c)
# svg doesn't support the "transparent" keyword; we need to manually
# refactor it into "transparent black"
if c.is_a?(Sass::Script::Value::String) && c.value == "transparent"
"black"
elsif c.is_a?(Sass::Script::Value::String)
c.value.dup
else
self.color_to_s(c.with(:alpha => 1))
end
end
def self.color_to_svg_alpha(c)
# svg doesn't support the "transparent" keyword; we need to manually
# refactor it into "transparent black"
if c.is_a?(Sass::Script::Value::String) && c.value == "transparent"
0
elsif c.is_a?(Sass::Script::Value::String) && c.value == "currentColor"
1
else
c.alpha
end
end
def self.color_to_s(c)
if c.is_a?(Sass::Script::Value::String)
c.value.dup
else
c.inspect.dup
end
end
def to_s(options = self.options)
s = self.class.color_to_s(color)
if stop
s << " "
if stop.respond_to?(:unitless?) && stop.unitless?
s << stop.times(number(100, "%")).inspect
else
s << stop.to_s
end
end
s
end
def to_sass(options = nil)
identifier("color-stop(#{color.to_sass rescue nil}, #{stop.to_sass rescue nil})")
end
end
module Gradient
include Sass::Script::Value::Helpers
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def standardized_prefix(prefix)
class_eval %Q<
def to_#{prefix}(options = self.options)
identifier("-#{prefix}-\#{to_s_prefixed(options)}")
end
>
end
end
def inspect
to_s
end
def supports?(aspect)
GRADIENT_ASPECTS.include?(aspect)
end
def has_aspect?
true
end
def is_position(pos)
pos.value =~ Compass::Core::SassExtensions::Functions::Constants::POSITIONS
end
def angle?(value)
value.is_a?(Sass::Script::Value::Number) &&
value.numerator_units.size == 1 &&
value.numerator_units.first == "deg" &&
value.denominator_units.empty?
end
end
class RadialGradient < Sass::Script::Value::Base
include Gradient
attr_accessor :position, :shape_and_size, :color_stops
def children
[color_stops, position, shape_and_size].compact
end
def initialize(position, shape_and_size, color_stops)
unless color_stops.value.size >= 2
raise Sass::SyntaxError, "At least two color stops are required for a radial-gradient"
end
if angle?(position)
raise Sass::SyntaxError, "CSS no longer allows angles in radial-gradients."
end
self.position = position
self.shape_and_size = shape_and_size
self.color_stops = color_stops
end
def to_s(options = self.options)
to_official.to_s
end
def to_s_prefixed(options = self.options)
to_s(options)
end
def supports?(aspect)
# I don't know how to support radial old webkit gradients (owg)
if %w(owg).include?(aspect)
false
else
super
end
end
standardized_prefix :webkit
standardized_prefix :moz
def to_webkit(options = self.options)
s = "-webkit-radial-gradient("
s << old_standard_arguments(options)
s << ")"
identifier(s)
end
def to_moz(options = self.options)
s = "-moz-radial-gradient("
s << old_standard_arguments(options)
s << ")"
identifier(s)
end
def to_official
s = "radial-gradient("
s << new_standard_arguments(options)
s << ")"
identifier(s)
end
def new_standard_arguments(options = self.options)
if shape_and_size
"#{array_to_s(shape_and_size, options)} at #{array_to_s(position, options)}, #{array_to_s(color_stops, options)}"
elsif position
"#{array_to_s(position, options)}, #{array_to_s(color_stops, options)}"
else
array_to_s(color_stops, options)
end
end
def old_standard_arguments(options = self.options)
if shape_and_size
"#{array_to_s(position, options)}, #{array_to_s(shape_and_size, options)}, #{array_to_s(color_stops, options)}"
elsif position
"#{array_to_s(position, options)}, #{array_to_s(color_stops, options)}"
else
array_to_s(color_stops, options)
end
end
def to_svg(options = self.options)
# XXX Add shape support if possible
radial_svg_gradient(color_stops, position || _center_position)
end
def to_css2(options = self.options)
null
end
def array_to_s(array, opts)
if array.is_a?(Sass::Script::Value::List)
array.to_s
else
l = list(array, :space)
l.options = opts
l.to_s
end
end
end
class LinearGradient < Sass::Script::Value::Base
include Gradient
attr_accessor :color_stops, :position_or_angle, :legacy
def children
[color_stops, position_or_angle].compact
end
def initialize(position_or_angle, color_stops, legacy=false)
unless color_stops.value.size >= 2
raise Sass::SyntaxError, "At least two color stops are required for a linear-gradient"
end
self.position_or_angle = position_or_angle
self.color_stops = color_stops
self.legacy = legacy
end
def to_s_prefixed(options = self.options)
s = "linear-gradient("
if legacy
s << position_or_angle.to_s(options) << ", " if position_or_angle
else
s << convert_to_or_from_legacy(position_or_angle, options) << ", " if position_or_angle
end
s << color_stops.to_s(options)
s << ")"
end
def convert_to_or_from_legacy(position_or_angle, options = self.options)
input = if position_or_angle.is_a?(Sass::Script::Value::Number)
position_or_angle
else
opts(list(position_or_angle.to_s.split(' ').map {|s| identifier(s) }, :space))
end
return convert_angle_from_offical(input).to_s(options)
end
def to_s(options = self.options)
s = 'linear-gradient('
if legacy
s << convert_to_or_from_legacy(position_or_angle, options) << ", " if position_or_angle
else
s << position_or_angle.to_s(options) << ", " if position_or_angle
end
s << color_stops.to_s(options)
s << ")"
end
standardized_prefix :webkit
standardized_prefix :moz
standardized_prefix :o
def supports?(aspect)
# I don't know how to support degree-based gradients in old webkit gradients (owg) or svg so we just disable them.
if %w(owg).include?(aspect) && position_or_angle.is_a?(Sass::Script::Value::Number) && position_or_angle.numerator_units.include?("deg")
false
elsif %w(owg svg).include?(aspect) && color_stops.value.any?{|cs| cs.stop.is_a?(Sass::Script::Value::String) }
# calc expressions cannot be represented in svg or owg
false
else
super
end
end
# Output the original webkit gradient syntax
def to_owg(options = self.options)
position_list = reverse_side_or_corner(position_or_angle)
start_point = grad_point(position_list)
args = []
args << start_point
args << linear_end_position(position_list, start_point, color_stops.value.last.stop)
args << grad_color_stops(color_stops)
args.each{|a| a.options = options}
Sass::Script::String.new("-webkit-gradient(linear, #{args.join(', ')})")
end
def to_svg(options = self.options)
linear_svg_gradient(color_stops, position_or_angle || identifier("top"))
end
def to_css2(options = self.options)
null
end
end
module Functions
include Sass::Script::Value::Helpers
def reverse_side_or_corner(position)
position_array = position.nil? ? [identifier('top')] : position.value.dup
if position_array.first == identifier('to')
# Remove the 'to' element from the array
position_array.shift
# Reverse all the positions
reversed_position = position_array.map do |pos|
opposite_position(pos)
end
else
# When the position does not have the 'to' element we don't need to
# reverse the direction of the gradient
reversed_position = position_array
end
opts(list(reversed_position, :space))
end
def convert_angle_from_offical(deg)
if deg.is_a?(Sass::Script::Value::Number)
return number((deg.value.to_f - 450).abs % 360, 'deg')
else
args = deg.value
direction = []
if args[0] == identifier('to')
if args.size < 2
direction = args
else
direction << opposite_position(args[1])
end
else
direction << identifier('to')
args.each do |pos|
direction << opposite_position(pos)
end
end
return opts(list(direction, :space))
end
end
# given a position list, return a corresponding position in percents
# otherwise, returns the original argument
def grad_point(position)
original_value = position
position = unless position.is_a?(Sass::Script::Value::List)
opts(list([position], :space))
else
opts(list(position.value.dup, position.separator))
end
# Handle unknown arguments by passing them along untouched.
unless position.value.all?{|p| is_position(p) }
return original_value
end
if (position.value.first.value =~ /top|bottom/) or (position.value.last.value =~ /left|right/)
# browsers are pretty forgiving of reversed positions so we are too.
position = opts(list(position.value.reverse, position.separator))
end
if position.value.size == 1
if position.value.first.value =~ /top|bottom/
position = opts(list(identifier("center"), position.value.first, position.separator))
elsif position.value.first.value =~ /left|right/
position = opts(list(position.value.first, identifier("center"), position.separator))
end
end
position = opts(list(position.value.map do |p|
case p.value
when /top|left/
number(0, "%")
when /bottom|right/
number(100, "%")
when /center/
number(50, "%")
else
p
end
end, position.separator))
position
end
def color_stops(*args)
opts(list(args.map do |arg|
if ColorStop === arg
arg
elsif Sass::Script::Value::Color === arg
ColorStop.new(arg)
elsif Sass::Script::Value::List === arg
ColorStop.new(*arg.value)
elsif Sass::Script::Value::String === arg && arg.value == "transparent"
ColorStop.new(arg)
elsif Sass::Script::Value::String === arg && arg.value == "currentColor"
ColorStop.new(arg)
else
raise Sass::SyntaxError, "Not a valid color stop: #{arg.class.name}: #{arg}"
end
end, :comma))
end
def radial_gradient(position_or_angle, shape_and_size, *color_stops)
# Have to deal with variable length/meaning arguments.
if color_stop?(shape_and_size)
color_stops.unshift(shape_and_size)
shape_and_size = nil
elsif list_of_color_stops?(shape_and_size)
# Support legacy use of the color-stops() function
color_stops = shape_and_size.value + color_stops
shape_and_size = nil
end
shape_and_size = nil if shape_and_size && !shape_and_size.to_bool # nil out explictly passed falses
# ditto for position_or_angle
if color_stop?(position_or_angle)
color_stops.unshift(position_or_angle)
position_or_angle = nil
elsif list_of_color_stops?(position_or_angle)
color_stops = position_or_angle.value + color_stops
position_or_angle = nil
end
position_or_angle = nil if position_or_angle && !position_or_angle.to_bool
# Support legacy use of the color-stops() function
if color_stops.size == 1 && list_of_color_stops?(color_stops.first)
color_stops = color_stops.first.value
end
if position_or_angle.is_a?(Sass::Script::Value::List) &&
(i = position_or_angle.value.index {|word| word.is_a?(Sass::Script::Value::String) && word.value == "at"})
shape_and_size = list(position_or_angle.value[0..(i-1)], :space)
shape_and_size.options = options
position_or_angle = list(position_or_angle.value[(i+1)..-1], :space)
position_or_angle.options = options
end
RadialGradient.new(position_or_angle, shape_and_size, send(:color_stops, *color_stops))
end
def _build_linear_gradient(position_or_angle, *color_stops)
if color_stop?(position_or_angle)
color_stops.unshift(position_or_angle)
position_or_angle = nil
elsif list_of_color_stops?(position_or_angle)
color_stops = position_or_angle.value + color_stops
position_or_angle = nil
end
position_or_angle = nil if position_or_angle && !position_or_angle.to_bool
# Support legacy use of the color-stops() function
if color_stops.size == 1 && (stops = list_of_color_stops?(color_stops.first))
color_stops = stops
end
return [position_or_angle, color_stops]
end
def _linear_gradient(position_or_angle, *color_stops)
position_or_angle, color_stops = _build_linear_gradient(position_or_angle, *color_stops)
LinearGradient.new(position_or_angle, send(:color_stops, *color_stops))
end
def _linear_gradient_legacy(position_or_angle, *color_stops)
position_or_angle, color_stops = _build_linear_gradient(position_or_angle, *color_stops)
LinearGradient.new(position_or_angle, send(:color_stops, *color_stops), true)
end
# returns color-stop() calls for use in webkit.
def grad_color_stops(color_list)
stops = color_stops_in_percentages(color_list).map do |stop, color|
Sass::Script::String.new("color-stop(#{stop.to_s}, #{ColorStop.color_to_s(color)})")
end
opts(list(stops, :comma))
end
def color_stops_in_percentages(color_list)
assert_type color_list, :List
color_list = normalize_stops(color_list)
max = color_list.value.last.stop
last_value = nil
color_list.value.map do |pos|
next [pos.stop, pos.color] if pos.stop.is_a?(Sass::Script::Value::String)
# have to convert absolute units to percentages for use in color stop functions.
stop = pos.stop
stop = stop.div(max).times(number(100, "%")) if stop.numerator_units == max.numerator_units && max.numerator_units != ["%"]
# Make sure the color stops are specified in the right order.
if last_value && stop.numerator_units == last_value.numerator_units && stop.denominator_units == last_value.denominator_units && (stop.value * 1000).round < (last_value.value * 1000).round
raise Sass::SyntaxError.new("Color stops must be specified in increasing order. #{stop.value} came after #{last_value.value}.")
end
last_value = stop
[stop, pos.color]
end
end
# only used for webkit
def linear_end_position(position_or_angle, start_point, end_target)
end_point = grad_point(opposite_position(position_or_angle))
if end_target && end_target.numerator_units == ["px"]
if start_point.value.first == end_point.value.first && start_point.value.last.value == 0
# this means top-to-bottom
new_end_point = end_point.value.dup
new_end_point[1] = number(end_target.value)
end_point = opts(list(new_end_point, end_point.separator))
elsif start_point.value.last == end_point.value.last && start_point.value.first.value == 0
# this implies left-to-right
new_end_point = end_point.value.dup
new_end_point[0] = number(end_target.value)
end_point = opts(list(new_end_point, end_point.separator))
end
end
end_point
end
# returns the end position of the gradient from the color stop
def grad_end_position(color_list, radial = bool(false))
assert_type color_list, :List
default = number(100)
grad_position(color_list, number(color_list.value.size), default, radial)
end
def grad_position(color_list, index, default, radial = bool(false))
assert_type color_list, :List
stop = color_list.value[index.value - 1].stop
if stop && radial.to_bool
orig_stop = stop
if stop.unitless?
if stop.value <= 1
# A unitless number is assumed to be a percentage when it's between 0 and 1
stop = stop.times(number(100, "%"))
else
# Otherwise, a unitless number is assumed to be in pixels
stop = stop.times(number(1, "px"))
end
end
if stop.numerator_units == ["%"] && color_list.value.last.stop && color_list.value.last.stop.numerator_units == ["px"]
stop = stop.times(color_list.value.last.stop).div(number(100, "%"))
end
Compass::Logger.new.record(:warning, "Webkit only supports pixels for the start and end stops for radial gradients. Got: #{orig_stop}") if stop.numerator_units != ["px"]
stop.div(Sass::Script::Value::Number.new(1, stop.numerator_units, stop.denominator_units))
elsif stop
stop
else
default
end
end
def linear_svg_gradient(color_stops, start)
converter = CSS3AngleToSVGConverter.new(start)
stops = color_stops_in_percentages(color_stops)
svg = linear_svg(stops, converter.x1, converter.y1, converter.x2, converter.y2)
inline_image_string(svg.gsub(/\s+/, ' '), 'image/svg+xml')
end
def radial_svg_gradient(color_stops, center)
cx, cy = *grad_point(center).value
r = grad_end_position(color_stops, bool(true))
stops = color_stops_in_percentages(color_stops)
svg = radial_svg(stops, cx, cy, r)
inline_image_string(svg.gsub(/\s+/, ' '), 'image/svg+xml')
end
private
def color_stop?(arg)
arg.is_a?(ColorStop) ||
(arg.is_a?(Sass::Script::Value::List) && ColorStop.new(*arg.value)) ||
ColorStop.new(arg)
rescue
nil
end
def normalize_stops(color_list)
positions = color_list.value.map{|obj| obj.dup}
# fill in the start and end positions, if unspecified
positions.first.stop = number(0) unless positions.first.stop
positions.last.stop = number(100, "%") unless positions.last.stop
# fill in empty values
for i in 0...positions.size
if positions[i].stop.nil?
num = 2.0
for j in (i+1)...positions.size
if positions[j].stop
positions[i].stop = positions[i-1].stop.plus((positions[j].stop.minus(positions[i-1].stop)).div(number(num)))
break
else
num += 1
end
end
end
end
# normalize unitless numbers
positions.each do |pos|
next pos if pos.stop.is_a?(Sass::Script::Value::String)
if pos.stop.unitless? && pos.stop.value <= 1
pos.stop = pos.stop.times(number(100, "%"))
elsif pos.stop.unitless?
pos.stop = pos.stop.times(number(1, "px"))
end
end
if (positions.last.stop.eq(number(0, "px")).to_bool ||
positions.last.stop.eq(number(0, "%")).to_bool)
raise Sass::SyntaxError.new("Color stops must be specified in increasing order")
end
opts(list(positions, color_list.separator))
end
def parse_color_stop(arg)
return ColorStop.new(arg) if arg.is_a?(Sass::Script::Value::Color)
return nil unless arg.is_a?(Sass::Script::Value::String)
color = stop = nil
expr = Sass::Script::Parser.parse(arg.value, 0, 0)
case expr
when Sass::Script::Value::Color
color = expr
when Sass::Script::Tree::Funcall
color = expr
when Sass::Script::Tree::Operation
unless [:concat, :space].include?(expr.instance_variable_get("@operator"))
# This should never happen.
raise Sass::SyntaxError, "Couldn't parse a color stop from: #{arg.value}"
end
color = expr.instance_variable_get("@operand1")
stop = expr.instance_variable_get("@operand2")
else
raise Sass::SyntaxError, "Couldn't parse a color stop from: #{arg.value}"
end
ColorStop.new(color, stop)
end
def list_of_color_stops?(arg)
if arg.respond_to?(:value)
arg.value.is_a?(Array) && arg.value.all?{|a| color_stop?(a)} ? arg.value : nil
elsif arg.is_a?(Array)
arg.all?{|a| color_stop?(a)} ? arg : nil
end
end
def linear_svg(color_stops, x1, y1, x2, y2)
gradient = %Q{#{color_stops_svg(color_stops)}}
svg(gradient)
end
def radial_svg(color_stops, cx, cy, r)
gradient = %Q{#{color_stops_svg(color_stops)}}
svg(gradient)
end
# color_stops = array of: [stop, color]
def color_stops_svg(color_stops)
color_stops.each.map{ |stop, color|
s = %{"
}.join
end
def svg(gradient)
svg = <<-EOS
EOS
end
def _center_position
opts(list(identifier("center"), identifier("center"), :space))
end
def opts(v)
v.options = options
v
end
end
module Assertions
def assert_type(value, type, name = nil)
return if value.is_a?(Sass::Script.const_get(type))
err = "#{value.inspect} is not a #{type.to_s.downcase}"
err = "$#{name}: " + err if name
raise ArgumentError.new(err)
end
end
class LinearGradient < Sass::Script::Value::Base
include Assertions
include Functions
include Compass::Core::SassExtensions::Functions::Constants
include Compass::Core::SassExtensions::Functions::InlineImage
end
class RadialGradient < Sass::Script::Value::Base
include Assertions
include Functions
include Compass::Core::SassExtensions::Functions::Constants
include Compass::Core::SassExtensions::Functions::InlineImage
end
end
================================================
FILE: core/lib/compass/core/sass_extensions/functions/image_size.rb
================================================
module Compass::Core::SassExtensions::Functions::ImageSize
KNOWN_TYPES = %w(png gif jpg jpeg)
# Returns the width of the image relative to the images directory
def image_width(image_file)
width, _ = image_dimensions(image_file)
number(width, "px")
end
# Returns the height of the image relative to the images directory
def image_height(image_file)
_, height = image_dimensions(image_file)
number(height, "px")
end
class ImageProperties
def initialize(file)
@file = (file.respond_to?(:to_path) ? file.to_path : file)
@file_type = File.extname(@file)[1..-1].downcase
unless KNOWN_TYPES.include?(@file_type)
raise Sass::SyntaxError, "Unrecognized file type: #{@file_type}"
end
end
def size
@dimensions ||= send(:"get_size_for_#{@file_type}")
end
private
def get_size_for_png
File.open(@file, "rb") {|io| io.read}[0x10..0x18].unpack('NN')
end
def get_size_for_gif
File.open(@file, "rb") {|io| io.read}[6..10].unpack('SS')
end
def get_size_for_jpg
get_size_for_jpeg
end
def get_size_for_jpeg
jpeg = JPEG.new(@file)
[jpeg.width, jpeg.height]
end
end
private
def image_dimensions(image_file)
image_file = image_file.respond_to?(:value) ? image_file.value : image_file
options[:compass] ||= {}
options[:compass][:image_dimensions] ||= {}
options[:compass][:image_dimensions][image_file] = ImageProperties.new(image_path_for_size(image_file)).size
end
def image_path_for_size(image_file)
if File.exists?(image_file)
return image_file
end
real_path(image_file)
end
def real_path(image_file)
# Compute the real path to the image on the file stystem if the images_dir is set.
if Compass.configuration.images_path
File.join(Compass.configuration.images_path, image_file)
else
File.join(Compass.configuration.project_path, image_file)
end
end
class JPEG
attr_reader :width, :height, :bits
def initialize(file)
if file.kind_of? IO
examine(file)
else
File.open(file, 'rb') { |io| examine(io) }
end
end
private
def examine(io)
class << io
unless method_defined?(:readbyte)
def readbyte
getc
end
end
def readint; (readbyte << 8) + readbyte; end
def readframe; read(readint - 2); end
def readsof; [readint, readbyte, readint, readint, readbyte]; end
def next
c = readbyte while c != 0xFF
c = readbyte while c == 0xFF
c
end
end
raise 'malformed JPEG!' unless io.readbyte == 0xFF && io.readbyte == 0xD8 # SOI
while marker = io.next
case marker
when 0xC0..0xC3, 0xC5..0xC7, 0xC9..0xCB, 0xCD..0xCF # SOF markers
length, @bits, @height, @width, components = io.readsof
raise 'malformed JPEG' unless length == 8 + components * 3
when 0xD9, 0xDA then break # EOI, SOS
when 0xFE then @comment = io.readframe # COM
when 0xE1 then io.readframe # APP1, contains EXIF tag
else io.readframe # ignore frame
end
end
end
end
end
================================================
FILE: core/lib/compass/core/sass_extensions/functions/inline_image.rb
================================================
module Compass::Core::SassExtensions::Functions::InlineImage
def inline_image(path, mime_type = nil)
path = path.value
real_path = File.join(Compass.configuration.images_path, path)
inline_image_string(data(real_path), compute_mime_type(path, mime_type))
end
def inline_font_files(*args)
files = []
with_each_font_file(*args) do |path, type|
path = path.value
real_path = File.join(Compass.configuration.fonts_path, path)
data = inline_image_string(data(real_path), compute_mime_type(path))
files << list(data, unquoted_string("format('#{type}')"), :space)
end
list(files, :comma)
end
protected
def inline_image_string(data, mime_type)
data = [data].flatten.pack('m').gsub("\n","")
url = "url('data:#{mime_type};base64,#{data}')"
unquoted_string(url)
end
private
def compute_mime_type(path, mime_type = nil)
return mime_type.value if mime_type
case path
when /\.png$/i
'image/png'
when /\.jpe?g$/i
'image/jpeg'
when /\.gif$/i
'image/gif'
when /\.svg$/i
'image/svg+xml'
when /\.otf$/i
'font/opentype'
when /\.eot$/i
'application/vnd.ms-fontobject'
when /\.ttf$/i
'font/truetype'
when /\.woff$/i
'application/font-woff'
when /\.off$/i
'font/openfont'
when /\.([a-zA-Z]+)$/
"image/#{Regexp.last_match(1).downcase}"
else
raise Compass::Error, "A mime type could not be determined for #{path}, please specify one explicitly."
end
end
def data(real_path)
if File.readable?(real_path)
File.open(real_path, "rb") {|io| io.read}
else
raise Compass::Error, "File not found or cannot be read: #{real_path}"
end
end
end
================================================
FILE: core/lib/compass/core/sass_extensions/functions/lists.rb
================================================
module Compass::Core::SassExtensions::Functions::Lists
# Returns true when the object is false, an empty string, or an empty list
def blank(obj)
case obj
when Sass::Script::Value::Bool, Sass::Script::Value::Null
bool(!obj.to_bool)
when Sass::Script::Value::String
bool(obj.value.strip.size == 0)
when Sass::Script::Value::List
bool(obj.value.size == 0 || obj.value.all?{|el| blank(el).to_bool})
else
bool(false)
end
end
# Returns a new list after removing any non-true values
def compact(*args)
sep = :comma
if args.size == 1 && args.first.is_a?(Sass::Script::Value::List)
list = args.first
args = list.value
sep = list.separator
end
list(args.reject{|a| !a.to_bool}, sep)
end
# Get the nth value from a list
def _compass_nth(list, place)
assert_type list, :List
if place.value == "first"
list.value.first
elsif place.value == "last"
list.value.last
else
list.value[place.value - 1]
end
end
# Returns a list object from a value that was passed.
# This can be used to unpack a space separated list that got turned
# into a string by sass before it was passed to a mixin.
def _compass_list(arg)
if arg.is_a?(Sass::Script::Value::List)
list(arg.value.dup, arg.separator)
else
list(arg, :space)
end
end
# If the argument is a list, it will return a new list that is space delimited
# Otherwise it returns a new, single element, space-delimited list.
def _compass_space_list(list)
if list.is_a?(Sass::Script::Value::List)
list(list.value.dup, :space)
else
list(list, :space)
end
end
# Returns the size of the list.
def _compass_list_size(list)
assert_list list
number(list.value.size)
end
# slice a sublist from a list
def _compass_slice(list, start_index, end_index = nil)
end_index ||= number(-1)
start_index = start_index.value
end_index = end_index.value
start_index -= 1 unless start_index < 0
end_index -= 1 unless end_index < 0
list(list.values[start_index..end_index], list.separator)
end
# removes the given values from the list.
def reject(list, *values)
list(list.value.reject{|v| values.any?{|o| v == o}}, list.separator)
end
# returns the first value of a space delimited list.
def first_value_of(list)
if list.is_a?(Sass::Script::Value::String)
r = list.value.split(/\s+/).first
list.type == :identifier ? identifier(r) : quoted_string(r)
elsif list.is_a?(Sass::Script::Value::List)
list.value.first
else
list
end
end
protected
def assert_list(value)
unless value.is_a?(Sass::Script::Value::List)
raise ArgumentError.new("#{value.inspect} is not a list")
end
end
end
================================================
FILE: core/lib/compass/core/sass_extensions/functions/math.rb
================================================
module Compass::Core::SassExtensions::Functions::Math
extend Compass::Core::SassExtensions::Functions::SassDeclarationHelper
extend Sass::Script::Value::Helpers
def self.included(base)
if base == Sass::Script::Functions
base.send :alias_method, :sass_random, :random
base.send :alias_method, :random, :deprecated_random
end
end
PI = number(Math::PI)
E = number(Math::E)
def pi()
PI
end
declare :pi, []
def deprecated_random(*args)
if args.length == 2
Compass::Util.compass_warn < h1, h2, h3, h4, h5, h6
# headers(4) => h1, h2, h3, h4
# headers(2,4) => h2, h3, h4
def headers(from = nil, to = nil)
if from && !to
if from.is_a?(Sass::Script::Value::String) && from.value == "all"
from = number(1)
to = number(6)
else
to = from
from = number(1)
end
else
from ||= number(1)
to ||= number(6)
end
list((from.value..to.value).map{|n| identifier("h#{n}")}, :comma)
end
alias headings headers
end
================================================
FILE: core/lib/compass/core/sass_extensions/functions/urls.rb
================================================
module Compass::Core::SassExtensions::Functions::Urls
def self.has?(base, instance_method)
Sass::Util.has?(:instance_method, base, instance_method)
end
def self.included(base)
base.send(:include, StylesheetUrl) unless has?(base, :stylesheet_url)
base.send(:include, FontUrl) unless has?(base, :font_url)
base.send(:include, ImageUrl) unless has?(base, :image_url)
base.send(:include, GeneratedImageUrl) unless has?(base, :generated_image_url)
end
module StylesheetUrl
def self.included(base)
if base.respond_to?(:declare)
base.declare :stylesheet_url, [:path]
base.declare :stylesheet_url, [:path, :only_path]
end
end
def stylesheet_url(path, only_path = bool(false))
# Compute the path to the stylesheet, either root relative or stylesheet relative
# or nil if the http_images_path is not set in the configuration.
http_stylesheets_path = if relative?
compute_relative_path(Compass.configuration.css_path)
elsif Compass.configuration.http_stylesheets_path
Compass.configuration.http_stylesheets_path
else
Compass.configuration.http_root_relative(Compass.configuration.css_dir)
end
path = "#{http_stylesheets_path}/#{path.value}"
if only_path.to_bool
unquoted_string(clean_path(path))
else
clean_url(path)
end
end
end
module FontUrl
def self.included(base)
if base.respond_to?(:declare)
base.declare :font_url, [:path]
base.declare :font_url, [:path, :only_path]
base.declare :font_url, [:path, :only_path, :cache_buster]
end
end
def font_url(path, only_path = bool(false), cache_buster = bool(true))
path = path.value # get to the string value of the literal.
# Short curcuit if they have provided an absolute url.
if absolute_path?(path)
return unquoted_string("url(#{path})")
end
# Compute the path to the font file, either root relative or stylesheet relative
# or nil if the http_fonts_path cannot be determined from the configuration.
http_fonts_path = if relative?
compute_relative_path(Compass.configuration.fonts_path)
else
Compass.configuration.http_fonts_path
end
# Compute the real path to the font on the file system if the fonts_dir is set.
real_path = if Compass.configuration.fonts_dir
File.join(Compass.configuration.fonts_path, path.gsub(/[?#].*$/,""))
end
# prepend the path to the font if there's one
if http_fonts_path
http_fonts_path = "#{http_fonts_path}/" unless http_fonts_path[-1..-1] == "/"
path = "#{http_fonts_path}#{path}"
end
# Compute the asset host unless in relative mode.
asset_host = if !relative? && Compass.configuration.asset_host
Compass.configuration.asset_host.call(path)
end
# Compute and append the cache buster if there is one.
if cache_buster.to_bool
path, anchor = path.split("#", 2)
if cache_buster.is_a?(Sass::Script::Value::String)
path += "#{path["?"] ? "&" : "?"}#{cache_buster.value}"
else
path = cache_busted_path(path, real_path)
end
path = "#{path}#{"#" if anchor}#{anchor}"
end
# prepend the asset host if there is one.
path = "#{asset_host}#{'/' unless path[0..0] == "/"}#{path}" if asset_host
if only_path.to_bool
unquoted_string(clean_path(path))
else
clean_url(path)
end
end
end
module ImageUrl
def self.included(base)
if base.respond_to?(:declare)
base.declare :image_url, [:path]
base.declare :image_url, [:path, :only_path]
base.declare :image_url, [:path, :only_path, :cache_buster]
end
end
def image_url(path, only_path = bool(false), cache_buster = bool(true))
path = path.value # get to the string value of the literal.
if path =~ %r{^#{Regexp.escape(Compass.configuration.http_images_path)}/(.*)}
# Treat root relative urls (without a protocol) like normal if they start with
# the images path.
path = $1
elsif absolute_path?(path)
# Short curcuit if they have provided an absolute url.
return unquoted_string("url(#{path})")
end
# Compute the path to the image, either root relative or stylesheet relative
# or nil if the http_images_path is not set in the configuration.
http_images_path = if relative?
compute_relative_path(Compass.configuration.images_path)
elsif Compass.configuration.http_images_path
Compass.configuration.http_images_path
else
Compass.configuration.http_root_relative(Compass.configuration.images_dir)
end
# Compute the real path to the image on the file stystem if the images_dir is set.
real_path = if Compass.configuration.images_path
File.join(Compass.configuration.images_path, path.gsub(/#.*$/,""))
else
File.join(Compass.configuration.project_path, path.gsub(/#.*$/,""))
end
# prepend the path to the image if there's one
if http_images_path
http_images_path = "#{http_images_path}/" unless http_images_path[-1..-1] == "/"
path = "#{http_images_path}#{path}"
end
# Compute the asset host unless in relative mode.
asset_host = if !relative? && Compass.configuration.asset_host
Compass.configuration.asset_host.call(path)
end
# Compute and append the cache buster if there is one.
if cache_buster.to_bool
path, anchor = path.split("#", 2)
if cache_buster.is_a?(Sass::Script::Value::String)
path += "#{path["?"] ? "&" : "?"}#{cache_buster.value}"
else
path = cache_busted_path(path, real_path)
end
path = "#{path}#{"#" if anchor}#{anchor}"
end
# prepend the asset host if there is one.
path = "#{asset_host}#{'/' unless path[0..0] == "/"}#{path}" if asset_host
if only_path.to_bool
unquoted_string(clean_path(path))
else
clean_url(path)
end
end
end
module GeneratedImageUrl
def self.included(base)
if base.respond_to?(:declare)
base.declare :generated_image_url, [:path]
base.declare :generated_image_url, [:path, :cache_buster]
end
end
def generated_image_url(path, cache_buster = bool(false))
path = path.value # get to the string value of the literal.
if path =~ %r{^#{Regexp.escape(Compass.configuration.http_generated_images_path)}/(.*)}
# Treat root relative urls (without a protocol) like normal if they start with
# the generated_images path.
path = $1
elsif absolute_path?(path)
# Short curcuit if they have provided an absolute url.
return unquoted_string("url(#{path})")
end
# Compute the path to the image, either root relative or stylesheet relative
# or nil if the http_generated_images_path is not set in the configuration.
http_generated_images_path = if relative?
compute_relative_path(Compass.configuration.generated_images_path)
elsif Compass.configuration.http_generated_images_path
Compass.configuration.http_generated_images_path
else
Compass.configuration.http_root_relative(Compass.configuration.generated_images_dir)
end
# Compute the real path to the image on the file stystem if the generated_images_dir is set.
real_path = if Compass.configuration.generated_images_path
File.join(Compass.configuration.generated_images_path, path.gsub(/#.*$/,""))
else
File.join(Compass.configuration.project_path, path.gsub(/#.*$/,""))
end
# prepend the path to the image if there's one
if http_generated_images_path
http_generated_images_path = "#{http_generated_images_path}/" unless http_generated_images_path[-1..-1] == "/"
path = "#{http_generated_images_path}#{path}"
end
# Compute the asset host unless in relative mode.
asset_host = if !relative? && Compass.configuration.asset_host
Compass.configuration.asset_host.call(path)
end
# Compute and append the cache buster if there is one.
if cache_buster.to_bool
path, anchor = path.split("#", 2)
if cache_buster.is_a?(Sass::Script::Value::String)
path += "#{path["?"] ? "&" : "?"}#{cache_buster.value}"
else
path = cache_busted_path(path, real_path)
end
path = "#{path}#{"#" if anchor}#{anchor}"
end
# prepend the asset host if there is one.
path = "#{asset_host}#{'/' unless path[0..0] == "/"}#{path}" if asset_host
clean_url(path)
end
end
private
# Emits a path, taking off any leading "./"
def clean_path(url)
url = url.to_s
url = url[0..1] == "./" ? url[2..-1] : url
end
# Emits a url, taking off any leading "./"
def clean_url(url)
unquoted_string("url('#{clean_path(url)}')")
end
def relative?
Compass.configuration.relative_assets?
end
def absolute_path?(path)
path[0..0] == "/" || path[0..3] == "http"
end
def compute_relative_path(path)
if (target_css_file = options[:css_filename])
target_path = Pathname.new(File.expand_path(path))
source_path = Pathname.new(File.dirname(File.expand_path(target_css_file)))
target_path.relative_path_from(source_path).to_s
end
end
def cache_busted_path(path, real_path)
cache_buster = compute_cache_buster(path, real_path)
if cache_buster.nil?
return path
elsif cache_buster.is_a?(String)
cache_buster = {:query => cache_buster}
else
path = cache_buster[:path] if cache_buster[:path]
end
if cache_buster[:query]
"#{path}#{path["?"] ? "&" : "?"}#{cache_buster[:query]}"
else
path
end
end
def compute_cache_buster(path, real_path)
file = nil
if Compass.configuration.asset_cache_buster
args = [path]
if Compass.configuration.asset_cache_buster.arity > 1
begin
file = File.new(real_path) if real_path
rescue Errno::ENOENT
# pass
end
args << file
end
Compass.configuration.asset_cache_buster.call(*args)
elsif real_path
default_cache_buster(path, real_path)
end
ensure
file.close if file
end
def default_cache_buster(path, real_path)
if File.readable?(real_path)
File.mtime(real_path).to_i.to_s
else
$stderr.puts "WARNING: '#{File.basename(path)}' was not found (or cannot be read) in #{File.dirname(real_path)}"
end
end
end
================================================
FILE: core/lib/compass/core/sass_extensions/functions.rb
================================================
module Compass::Core::SassExtensions::Functions
module SassDeclarationHelper
def declare(*args)
Sass::Script::Functions.declare(*args)
end
end
end
%w(
selectors enumerate urls display
inline_image image_size constants gradient_support
font_files lists colors math
env cross_browser_support configuration
files
).each do |func|
require "compass/core/sass_extensions/functions/#{func}"
end
module Sass::Script::Functions
include Compass::Core::SassExtensions::Functions::Configuration
include Compass::Core::SassExtensions::Functions::Selectors
include Compass::Core::SassExtensions::Functions::Enumerate
include Compass::Core::SassExtensions::Functions::Urls
include Compass::Core::SassExtensions::Functions::Display
include Compass::Core::SassExtensions::Functions::InlineImage
include Compass::Core::SassExtensions::Functions::ImageSize
include Compass::Core::SassExtensions::Functions::GradientSupport::Functions
include Compass::Core::SassExtensions::Functions::FontFiles
include Compass::Core::SassExtensions::Functions::Files
include Compass::Core::SassExtensions::Functions::Constants
include Compass::Core::SassExtensions::Functions::Lists
include Compass::Core::SassExtensions::Functions::Colors
include Compass::Core::SassExtensions::Functions::Math
include Compass::Core::SassExtensions::Functions::CrossBrowserSupport
include Compass::Core::SassExtensions::Functions::Env
end
# Wierd that this has to be re-included to pick up sub-modules. Ruby bug?
class Sass::Script::Functions::EvaluationContext
include Sass::Script::Functions
end
================================================
FILE: core/lib/compass/core/sass_extensions/monkey_patches/browser_support.rb
================================================
require 'sass/script'
module Sass::Script
module Value
class Base
NO_CHILDREN = []
def children
NO_CHILDREN
end
def opts(value)
value.options = options
value
end
end
class List < Base
def children
value
end
end
class ArgList < List
def children
super + @keywords.values
end
end
class Map < Base
def children
to_a
end
end
end
module HasSimpleCrossBrowserFunctionSupport
def supports?(aspect)
return true if Compass::BrowserSupport.supports?(name, aspect)
children.any? {|child| child.respond_to?(:supports?) && child.supports?(aspect) }
end
def has_aspect?(children = nil)
children ||= self.children
return true if Compass::BrowserSupport.has_aspect?(name)
children.any? {|child| child.respond_to?(:has_aspect?) && child.has_aspect? }
end
end
class CrossBrowserFunctionCall < Literal
attr_accessor :name, :args
include HasSimpleCrossBrowserFunctionSupport
include Sass::Script::Value::Helpers
def initialize(name, args)
self.name = name
self.args = args
end
def children
args
end
def inspect
to_s
end
def to_s(options = self.options)
"#{name}(#{args.map{|a| a.to_s(options)}.join(", ")})"
end
%w(webkit moz o ms svg css2 owg).each do |prefix|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
def to_#{prefix}(options = self.options)
prefixed_args = args.map do |arg|
arg.respond_to?(:to_#{prefix}) ? arg.to_#{prefix}(options) : arg
end
prefixed_name = if Compass::BrowserSupport.supports?(name, "#{prefix}")
"-#{prefix}-\#{name}"
else
name
end
contents = prefixed_args.join(', ')
if contents.size > 0
opts(identifier("\#{prefixed_name}(\#{contents})"))
else
opts(null)
end
end
RUBY
end
end
class Funcall < Node
include HasSimpleCrossBrowserFunctionSupport
alias sass_to_value to_value
def to_value(args)
if has_aspect?(args)
CrossBrowserFunctionCall.new(name, args)
else
sass_to_value(args)
end
end
end
class List < Literal
def supports?(aspect)
children.any? {|child| child.respond_to?(:supports?) && child.supports?(aspect) }
end
def has_aspect?
children.any? {|child| child.respond_to?(:has_aspect?) && child.has_aspect? }
end
end
end
================================================
FILE: core/lib/compass/core/sass_extensions/monkey_patches/traversal.rb
================================================
module Sass
module Tree
class Node
unless method_defined?(:visit_depth_first)
def visit_depth_first(visitor)
visitor.visit(self)
visitor.down(self) if children.any? and visitor.respond_to?(:down)
if is_a?(ImportNode) && visitor.import?(self)
root = Sass::Engine.for_file(import, @options).to_tree
imported_children = root.children
end
(imported_children || children).each do |child|
break if visitor.respond_to?(:stop?) && visitor.stop?
child.visit_depth_first(visitor)
end
visitor.up(self) if children.any?
end
end
end
end
end
================================================
FILE: core/lib/compass/core/sass_extensions/monkey_patches.rb
================================================
%w(traversal browser_support).each do |patch|
require "compass/core/sass_extensions/monkey_patches/#{patch}"
end
================================================
FILE: core/lib/compass/core/sass_extensions.rb
================================================
require 'sass'
unless Sass::Script::Functions.methods.grep(/\Adeclare\Z/).any?
raise LoadError, "It looks like you've got an incompatible version of Sass. This often happens when you have an old haml gem installed. Please upgrade Haml to v3.1 or above."
end
module Compass::Core::SassExtensions
end
require 'compass/core/sass_extensions/functions'
require 'compass/core/sass_extensions/monkey_patches'
================================================
FILE: core/lib/compass/core/version.rb
================================================
require 'compass/core/generated_version'
module Compass
module Core
unless defined?(::Compass::Core::VERSION)
def self.scope(file)
File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", file))
end
VERSION = File.read(scope("VERSION")).strip
end
end
end
================================================
FILE: core/lib/compass/core.rb
================================================
require "compass/core/version"
module Compass
module Core
class << self
attr_accessor :module_deprecation_warning_issued
end
def base_directory(*subdirs)
File.expand_path(File.join(File.dirname(__FILE__), '..', "..", *subdirs))
end
def lib_directory(*subdirs)
File.expand_path(File.join(File.dirname(__FILE__), "..", *subdirs))
end
module_function :base_directory, :lib_directory
end
module HasDeprecatedConstantsFromCore
def self.extended(base)
new_base = base.name.sub(/^Compass/,"Compass::Core")
base.class_eval <<-RUBY
def self.const_missing(const_name)
puts "cannot find \#{const_name}"
if #{new_base}.const_defined?(const_name)
unless Compass::Core.module_deprecation_warning_issued
Compass::Core.module_deprecation_warning_issued = true
Compass::Util.compass_warn(
"DEPRECATED: #{base.name}::\#{const_name} has been moved to " +
"#{new_base}::\#{const_name}.\\n" +
"Please update \#{caller[0]}")
end
#{new_base}.const_get(const_name)
end
end
RUBY
end
end
extend HasDeprecatedConstantsFromCore
module SassExtensions
extend HasDeprecatedConstantsFromCore
module Functions
extend HasDeprecatedConstantsFromCore
end
end
def shared_extension_paths
@shared_extension_paths ||= begin
if ENV["HOME"] && File.directory?(ENV["HOME"])
[File.join(ENV["HOME"], ".compass", "extensions")]
else
[]
end
rescue ArgumentError # If HOME is relative
[]
end
end
module_function :shared_extension_paths
end
require "sass"
require "sass/plugin"
require 'compass/util'
require "compass/frameworks"
require "compass/core/caniuse"
require 'compass/core/sass_extensions'
require 'compass/error'
require 'compass/browser_support'
require 'compass/configuration'
Compass::Frameworks.register(
"compass",
:stylesheets_directory => Compass::Core.base_directory("stylesheets"),
:templates_directory => Compass::Core.base_directory("templates"),
:version => Compass::Core::VERSION
)
================================================
FILE: core/lib/compass/error.rb
================================================
module Compass
class Error < Sass::SyntaxError
end
end
================================================
FILE: core/lib/compass/frameworks.rb
================================================
module Compass
module Frameworks
extend self
ALL = []
class Framework
attr_accessor :name
attr_accessor :path
attr_accessor :version
attr_accessor :templates_directory, :stylesheets_directory
def initialize(name, *arguments)
options = arguments.last.is_a?(Hash) ? arguments.pop : {}
self.path = path = options[:path] || arguments.shift
@name = name
@templates_directory = options[:templates_directory]
@templates_directory ||= File.join(path, 'templates') if path
@stylesheets_directory = options[:stylesheets_directory]
@stylesheets_directory ||= File.join(path, 'stylesheets') if path
@version = options[:version]
end
def template_directories
if templates_directory
Dir.glob(File.join(templates_directory, "*")).map{|f| File.basename(f)}
else
[]
end
end
def manifest_file(pattern)
File.join(templates_directory, pattern.to_s, "manifest.rb")
end
def manifest(pattern, options = {})
options[:pattern_name] ||= pattern
Compass::Installers::Manifest.new(manifest_file(pattern), options)
end
end
def detect_registration
@registered = nil
yield
@registered
ensure
@registered = nil
end
def register(name, *arguments)
opts = if arguments.last.is_a?(Hash)
arguments.last
else
o = {}
arguments << o
o
end
opts[:version] ||= guess_gem_version(caller[0])
@registered = Framework.new(name, *arguments)
if idx = ALL.index(self[name])
ALL[idx] = @registered
else
ALL << @registered
end
end
def [](name)
ALL.detect{|f| f.name.to_s == name.to_s}
end
def guess_gem_version(line_reference)
if line_reference =~ %r{/gems/([^/]*-[^/]*)/}
split_at = $1.rindex("-")
name = $1[1...split_at]
version = $1[(split_at + 1)..-1]
version unless name == "compass"
end
end
def discover(frameworks_directory)
if frameworks_directory == :defaults
warn("The :defaults argument to Compass::Frameworks.discover is no longer necessary")
return
end
frameworks_directory = Dir.new(frameworks_directory) unless frameworks_directory.is_a?(Dir)
dirs = frameworks_directory.entries.reject{|e| e =~ /^\./}.sort_by{|n| n =~ /^_/ ? n[1..-1] : n}
dirs.each do |framework|
register_directory File.join(frameworks_directory.path, framework)
end
end
def register_directory(directory)
loaders = [
File.join(directory, "compass_init.rb"),
File.join(directory, 'lib', File.basename(directory)+".rb"),
File.join(directory, File.basename(directory)+".rb")
]
loader = loaders.detect{|l| File.exists?(l)}
registered_framework = detect_registration do
require loader if loader
end
unless registered_framework
register File.basename(directory), directory
end
end
def template_exists?(template)
framework_name, template = template.split(%r{/}, 2)
template ||= "project"
if (framework = self[framework_name]) && framework.templates_directory
return File.directory?(File.join(framework.templates_directory, template))
end
false
end
def template_usage(template)
framework_name, template = template.split(%r{/}, 2)
framework = self[framework_name]
template ||= "project"
usage_file = File.join(framework.templates_directory, template, "USAGE.markdown")
if File.exists?(usage_file)
File.read(usage_file)
elsif help = framework.manifest(template).help
help
else
<<-END.gsub(/^ {8}/, '')
No Usage!
END
end
end
def pretty_print(skip_patterns = false)
result = ""
max = Compass::Frameworks::ALL.inject(0) do |gm, framework|
fm = framework.template_directories.inject(0) do |lm,pattern|
[lm, 7 + framework.name.size + pattern.size].max
end
[gm, fm].max
end
Compass::Frameworks::ALL.each do |framework|
next if framework.name =~ /^_/
result << " * #{framework.name}\n"
unless skip_patterns
framework.template_directories.each do |pattern|
result << " - #{framework.name}/#{pattern}".ljust(max)
if description = framework.manifest(pattern).description
result << " - #{description}"
end
result << "\n"
end
end
end
result
end
end
class << self
def discover_gem_extensions!
if defined?(Gem)
Gem.find_files("compass-*").map{|f| File.basename(f, ".rb")}.each do |compass_extension|
begin
require compass_extension
rescue Gem::LoadError, LoadError
Compass::Util.compass_warn "Unable to load extension: #{compass_extension}"
end
end
end
end
def discover_extensions!
Compass.shared_extension_paths.each do |extensions_path|
if File.directory?(extensions_path)
Compass::Frameworks.discover(extensions_path)
end
end
if File.directory?(configuration.extensions_path)
Compass::Frameworks.discover(configuration.extensions_path)
end
discover_gem_extensions!
end
end
end
================================================
FILE: core/lib/compass/util.rb
================================================
module Compass::Util
extend self
def compass_warn(*args)
Sass::Util.sass_warn(*args)
end
def blank?(value)
case value
when NilClass, FalseClass
true
when String, Array
value.length.zero?
else
false
end
end
end
================================================
FILE: core/lib/compass-core.rb
================================================
require 'compass/core'
================================================
FILE: core/stylesheets/_compass.scss
================================================
@import "compass/utilities";
@import "compass/typography";
@import "compass/css3";
================================================
FILE: core/stylesheets/_lemonade.scss
================================================
@mixin image-dimensions($file) {
height: image-height($file);
width: image-width($file);
}
@mixin sprite-image($file) {
background: sprite-image($file) $repeat;
}
@mixin sized-sprite-image($file) {
background: sprite-image($file);
@include image-dimensions($file);
}
@mixin sprite-folder($folder, $image-dimensions: false) {
.#{$folder} {
@if $image-dimensions {
background: sprite-url($folder);
}
@else {
background: sprite-url($folder) no-repeat;
}
}
@for $i from 0 to sprite-files-in-folder($folder) {
$file: sprite-file-from-folder($folder, $i);
.#{$folder}-#{image-basename($file)} {
@extend .#{$folder};
background-position: sprite-position(sprite-file-from-folder($folder, $i));
@if $image-dimensions {
@include image-dimensions($file);
}
}
}
}
@mixin sized-sprite-folder($folder) {
@include sprite-folder($folder, true);
}
================================================
FILE: core/stylesheets/compass/_configuration.scss
================================================
$project-path: null !default;
$debug-configuration: false !default;
$compass-initialized: false !default;
$compass-configured: false !default;
@mixin debug-compass-configuration {
@if $debug-configuration {
/* Compass Configuration: */
@each $setting, $value in compass-configuration() {
/* #{$setting}: #{inspect($value)} */
}
}
}
// This mixin resets the compass configuration
// and then initializes it with the sass options
// set in the environment. It is immediately called during import.
// It's unlikely you'll need to call this mixin yourself.
@mixin compass-initializer($project-path: $project-path) {
@if not $compass-initialized and not using-compass-compiler() {
$default-configuration: reset-configuration();
$default-configuration: add-sass-configuration($project-path);
}
$compass-initialized: true !global;
@include debug-compass-configuration;
}
@include compass-initializer;
// `$options`:
// A map of compass configuration options.
// E.g. @include compass-configuration((asset-host:
// Keywords style ar
// `$reconfigure`:
// When unset, if compass-configuration is called more than once, a warning will
// be issued and all calls after the first will be ignored.
// When set to `false`, all subsequent calls will be ignored without a warning.
// When set to `true`, the configuration will be added to any existing configuration.
@mixin compass-configuration($options: (), $reconfigure: null, $arguments...) {
@if not at-stylesheet-root() {
// this should be @error once that exists.
@warn "include compass-configuration from the root level of your stylesheet."
}
@if not $compass-configured or $reconfigure {
$options: map-merge($options, keywords($arguments));
@if length($arguments) > 0 {
@warn "compass-configuration accepts keyword arguments or a single map of options. Got: #{inspect($arguments)}."
}
$invoke: add-configuration($options);
@include debug-compass-configuration;
$compass-configured: true !global;
} @else if $reconfigure == null {
@warn "Compass was already configured for this stylesheet."
}
}
================================================
FILE: core/stylesheets/compass/_css3.scss
================================================
@import "css3/border-radius";
@import "css3/inline-block";
@import "css3/opacity";
@import "css3/box-shadow";
@import "css3/text-shadow";
@import "css3/columns";
@import "css3/box-sizing";
@import "css3/flexbox";
@import "css3/images";
@import "css3/background-clip";
@import "css3/background-origin";
@import "css3/background-size";
@import "css3/font-face";
@import "css3/transform";
@import "css3/transition";
@import "css3/appearance";
@import "css3/animation";
@import "css3/regions";
@import "css3/hyphenation";
@import "css3/filter";
@import "css3/user-interface";
================================================
FILE: core/stylesheets/compass/_layout.scss
================================================
@import "layout/grid-background";
@import "layout/sticky-footer";
@import "layout/stretching";
================================================
FILE: core/stylesheets/compass/_reset-legacy.scss
================================================
@import "reset/utilities-legacy";
@include global-reset;
================================================
FILE: core/stylesheets/compass/_reset.scss
================================================
@import "reset/utilities";
@include global-reset;
================================================
FILE: core/stylesheets/compass/_support.scss
================================================
// Map of compass extensions that are loaded. The value will either be
// the version of the extension or `true` if the version is unknown.
$compass-extensions: compass-extensions() !default;
// The list of browsers you want to support.
// Defaults to all.
$supported-browsers: browsers() !default;
// The browser usage threshold for features that gracefully degrade
// Defaults to 1 user in 1,000.
$graceful-usage-threshold: 0.1 !default;
// The browser usage threshold for features that cannot degrade gracefully
// Defaults to 1 user in 10,000.
$critical-usage-threshold: 0.01 !default;
// Set this to true to generate comments that will explain why a prefix was included or omitted.
$debug-browser-support: false !default;
// Minimum browser versions that must be supported.
// The keys of this map are any valid browser according to `browsers()`.
// The values of this map are the min version that is valid for that browser
// according to `browser-versions($browser)`
$browser-minimum-versions: (
'chrome': null,
'firefox': null,
'ie': null,
'safari': null,
'opera': null
) !default;
// @private
$default-capability-options: (
(full-support: true),
(partial-support: true)
);
// When a prefix in in context, but there is no current prefix
// That context is recorded here so other prefixes can be avoided.
$prefix-context: null;
// When a prefix is in a selector or directive scope, this is set to the
// current prefix value. When `null`, either there is no prefix in scope
// or the official prefix is being rendered. The `$prefix-context`
// variable can be used to make that distinction.
$current-prefix: null;
// When in a context that only exists in a particular version
// this variable is set to those versions.
$current-browser-versions: ();
// The legacy support CSS 2.1 Selectors.
// Defaults to the $critical-usage-threshold.
$css-sel2-support-threshold: $critical-usage-threshold !default;
// Check if the browser is in scope given the browser support and current prefix minimums.
@function browser-out-of-scope($browser, $version: null) {
@if not index($supported-browsers, $browser) {
@if $debug-browser-support {
@return "#{$browser} is not listed as a supported browser."
} @else {
@return true;
}
} @else if not ($current-prefix == null or $current-prefix == browser-prefix($browser)) {
@if $debug-browser-support {
@return "#{$browser} #{$version} is incompatible with #{$current-prefix}."
} @else {
@return true;
}
}
$current-range: map-get($current-browser-versions, $browser);
$current-min: if($current-range, nth($current-range, 1), null);
$current-max: if($current-range, nth($current-range, 2), null);
@if not ($version and $current-max) {
// We don't have any versions to compare
@return false;
} @else {
// If the version is less than the current min, it is not supported
$too-old: compare-browser-versions($browser, $version, $current-min) < 0;
$too-new: compare-browser-versions($browser, $version, $current-max) > 0;
@if $too-old or $too-new {
@if $debug-browser-support {
@return "The current scope only works with #{display-browser-range($browser, $current-min, $current-max)}.";
} @else {
@return true;
}
} @else {
@return false;
}
}
}
// Check whether the browser is supported according to the supported browsers,
// declared minimum support and usage thresholds.
@function support-legacy-browser($browser, $min-version, $max-version: null, $threshold: $critical-usage-threshold) {
@if not index($supported-browsers, $browser) {
@return false;
}
// Check agaist usage stats and declared minimums
$min-required-version: map-get($browser-minimum-versions, $browser);
$usage: if($max-version,
omitted-usage($browser, $min-version, $max-version),
omitted-usage($browser, $min-version));
@return $usage > $threshold or
($min-required-version and
compare-browser-versions($browser, $max-version or $min-version, $min-required-version) >= 0);
}
// Include content for a legacy browser
// Version can be a single version string or a list of versions ordered from oldest to newest.
@mixin for-legacy-browser($browser, $min-version, $max-version: $min-version,
$threshold: $critical-usage-threshold,
$ranges: ($browser: $min-version $max-version)) {
@if not browser-out-of-scope($browser, $max-version) and
support-legacy-browser($browser, $min-version, $max-version, $threshold)
{
@if $debug-browser-support {
/* Content for #{display-browser-range($browser, $min-version, $max-version)}.
Min version: #{map-get($browser-minimum-versions, $browser) or unspecified}.
User threshold to keep: #{$threshold}%. If #{display-browser-range($browser, $min-version, $max-version)} are omitted: #{omitted-usage($browser, $min-version, $max-version)}%. */
}
@include with-browser-ranges(intersect-browser-ranges($current-browser-versions, $ranges)) {
@content;
}
} @else if $debug-browser-support and browser-out-of-scope($browser, $max-version) {
/* Content for #{display-browser-range($browser, $min-version, $max-version)} omitted.
Not allowed in the current scope: #{browser-out-of-scope($browser, $max-version)} */
} @else if $debug-browser-support and not
support-legacy-browser($browser, $min-version, $max-version, $threshold) {
@if omitted-usage($browser, $min-version, $max-version) > $threshold {
/* Content for #{display-browser-range($browser, $min-version, $max-version)} omitted.
User threshold to keep: #{$threshold}%. If #{display-browser-range($browser, $min-version, $max-version)} and below are omitted: #{omitted-usage($browser, $min-version, $max-version)}%. */
} @else {
/* Content for #{display-browser-range($browser, $min-version, $max-version)} omitted.
Minimum support is #{map-get($browser-minimum-versions, $browser)}. */
}
}
}
@function display-browser-range($browser, $min-version, $max-version: $min-version) {
@return "#{unquote($browser)} #{unquote($min-version)}#{if($max-version != $min-version, unquote(' -') unquote($max-version), null)}";
}
// Renders the content once if any of the legacy browsers are supported.
// $browsers is a map of browser name to version ranges
@mixin for-legacy-browsers($browsers, $threshold: $critical-usage-threshold) {
$rendered: false;
@each $browser, $range in $browsers {
@if not $rendered {
@include for-legacy-browser($browser, $range..., $threshold: $threshold, $ranges: $browsers) {
$rendered: true;
@content;
}
}
}
}
// If there's a prefix context in scope, this will only output the content if the prefix matches.
// Otherwise, sets the current prefix scope and outputs the content.
@mixin with-prefix($prefix) {
@if $current-prefix or $prefix-context {
@if $current-prefix == $prefix or $prefix-context == $prefix {
@if $debug-browser-support {
@if $prefix {
/* content for #{$prefix} because #{$current-prefix or $prefix-context} is already in scope. */
} @else {
/* unprefixed content. #{$current-prefix or $prefix-context} is already in scope. */
}
}
$old-prefix-context: $prefix-context;
$old-prefix: $current-prefix;
$prefix-context: $prefix-context or $current-prefix !global;
$current-prefix: $prefix !global;
@content;
$prefix-context: $old-prefix-context !global;
$current-prefix: $old-prefix !global;
} @else if $prefix == null {
$old-prefix-context: $prefix-context;
$prefix-context: $prefix-context or $current-prefix !global;
$current-prefix: null !global;
@if $debug-browser-support {
/* Content for official syntax. Prefix context is still #{$prefix-context}. */
}
@content;
$current-prefix: $prefix-context !global;
$prefix-context: $old-prefix-context !global;
} @else if $debug-browser-support {
/* Omitting content for #{$prefix} because #{$current-prefix} is already in scope. */
}
} @else {
@if $debug-browser-support and $prefix {
/* Creating new #{$prefix} context. */
}
$prefix-context: $prefix !global;
$current-prefix: $prefix !global;
@content;
$current-prefix: null !global;
$prefix-context: null !global;
}
}
@function prefixes-for-capability($capability, $threshold, $capability-options: $default-capability-options) {
$result: ();
@each $prefix in browser-prefixes($supported-browsers) {
$result: map-merge($result,
($prefix: use-prefix($prefix, $capability, $threshold, $capability-options)));
}
@return $result;
}
// Yields to the mixin content once for each prefix required.
// The current prefix is set to the $current-prefix global for use by the included content.
// Also yields to the content once with $current-prefix set to null for the official version
// as long as there's not already a prefix in scope.
@mixin with-each-prefix($capability, $threshold, $capability-options: $default-capability-options) {
@each $prefix, $should-use-prefix in prefixes-for-capability($capability, $threshold, $capability-options) {
@if $should-use-prefix {
@if $debug-browser-support and type-of($should-use-prefix) == list {
/* Capability #{$capability} is prefixed with #{$prefix} because #{$should-use-prefix} is required. */
} @else if $debug-browser-support and type-of($should-use-prefix) == number {
/* Capability #{$capability} is prefixed with #{$prefix} because #{$should-use-prefix}% of users need it which is more than the threshold of #{$threshold}%. */
}
@include with-prefix($prefix) {
@include with-browser-ranges($capability) {
@content;
}
}
} @else if $debug-browser-support {
/* Capability #{$capability} is not prefixed with #{$prefix} because #{prefix-usage($prefix, $capability, $capability-options)}% of users are affected which is less than the threshold of #{$threshold}. */
}
}
@include with-prefix(null) {
@include with-browser-ranges($capability) {
@content;
}
}
}
// Returns true if at least one browser-version pair in $subset-ranges
// is a higher (or same) version than the browser-version pairs in
// $ranges.
@function has-browser-subset($ranges, $subset-ranges) {
$found-mismatch: false;
@each $browser, $subset-range in $subset-ranges {
$range: map-get($ranges, $browser);
@if $range {
$min-1: nth($subset-range, 1);
$max-1: nth($subset-range, 2);
$min-2: nth($range, 1);
$max-2: nth($range, 2);
@if (compare-browser-versions($browser, $min-2, $min-1) <= 0 and
compare-browser-versions($browser, $min-1, $max-2) <= 0) or
(compare-browser-versions($browser, $min-2, $max-1) <= 0 and
compare-browser-versions($browser, $max-1, $max-2) <= 0) or
(compare-browser-versions($browser, $min-1, $min-2) <= 0 and
compare-browser-versions($browser, $max-1, $max-2) >= 0) or
(compare-browser-versions($browser, $min-1, $min-2) >= 0 and
compare-browser-versions($browser, $max-1, $max-2) <= 0) {
@return true;
} @else {
$found-mismatch: true
}
}
}
@return not $found-mismatch;
}
// When the same browser is in both maps, then the minimum will be set
// to the maximum of the two minimum versions, and the maximum will be
// set to the minmum of the two maximum versions.
@function intersect-browser-ranges($ranges, $new-ranges) {
@each $browser, $new-range in $new-ranges {
$old-range: map-get($ranges, $browser);
@if $old-range {
$old-min: nth($old-range, 1);
$old-max: if(length($old-range) == 1, $old-min, nth($old-range, 2));
$new-min: nth($new-range, 1);
$new-max: if(length($new-range) == 1, $new-min, nth($new-range, 2));
$maximin: if(compare-browser-versions($browser, $old-min, $new-min) > 0,
$old-min, $new-min);
$minimax: if(compare-browser-versions($browser, $old-max, $new-max) < 0,
$old-max, $new-max);
$ranges: map-merge($ranges, ($browser: $maximin $minimax));
} @else {
$ranges: map-merge($ranges, ($browser: $new-range));
}
}
@return $ranges;
}
// If passed a map, that will be the new browser ranges.
// Otherwise a range map will be created based on the given capability and prefix
// using the `browser-ranges($capability, $prefix)` function.
//
// If there are current ranges in scope and the new ranges have some overlap
// with the current,
//
// If there is no overlap, then the content will not be rendered.
@mixin with-browser-ranges($capability, $prefix: $current-prefix) {
$new-ranges: null;
@if type-of($capability) == map {
$new-ranges: $capability;
} @else {
$new-ranges: browser-ranges($capability, $prefix);
}
@if has-browser-subset($current-browser-versions, $new-ranges) {
$old-ranges: $current-browser-versions;
$current-browser-versions: intersect-browser-ranges($old-ranges, $new-ranges) !global;
@content;
$current-browser-versions: $old-ranges !global;
} @else if $debug-browser-support {
/* Excluding content because #{inspect($new-ranges)} is not included within
#{inspect($current-browser-versions)} */
}
}
// Returns true if the prefixed usage stats for the capability exceed the threshold
// or if the minimum version for a supported browser would require a prefix for the capability.
@function use-prefix($prefix, $capability, $threshold, $capability-options: $default-capability-options) {
$usage: prefix-usage($prefix, $capability, $capability-options);
@if $usage > $threshold {
@return $usage;
} @else {
@each $browser in browsers($prefix) {
@if index($supported-browsers, $browser) {
$min-version: map-get($browser-minimum-versions, $browser);
@if $min-version {
$actual-prefix: browser-requires-prefix($browser, $min-version, $capability, $capability-options);
@if $actual-prefix and $prefix == $actual-prefix {
@return $browser $min-version;
}
}
}
}
}
@return false;
}
@function prefix-identifier($ident, $prefix: $current-prefix) {
@return unquote("#{$prefix}#{if($prefix, '-', null)}#{$ident}");
}
// Output a property and value using the current prefix.
// It will be unprefixed if $current-prefix is null.
@mixin prefix-prop($property, $value, $prefix: $current-prefix) {
#{prefix-identifier($property, $prefix)}: $value;
}
// Emit a set of properties with the prefix governed by the capability and usage threshold given.
//
// Example:
//
// @include prefixed-properties(css-animation, $animation-support-threshold,
// (animation-name: foo, animation-duration: 2s)
// );
@mixin prefixed-properties($capability, $threshold, $properties, $capability-options: $default-capability-options) {
@include with-each-prefix($capability, $threshold, $capability-options) {
@each $prop, $value in $properties {
@include prefix-prop($prop, $value);
}
}
}
// @private
@function warn-about-old-variables() {
$old-variables-in-use: ();
@each $old-variable-name in
(legacy-support-for-ie, legacy-support-for-ie6, legacy-support-for-ie7,
legacy-support-for-ie8, legacy-support-for-mozilla, legacy-support-for-webkit,
experimental-support-for-mozilla, experimental-support-for-webkit,
experimental-support-for-opera, experimental-support-for-microsoft,
experimental-support-for-khtml, experimental-support-for-svg)
{
@if global-variable-exists($old-variable-name) {
$old-variables-in-use: append($old-variables-in-use,
unquote("$#{$old-variable-name}"), comma);
}
}
@if length($old-variables-in-use) > 0 {
@warn "Compass has changed how browser support is configured. " +
"The following configuration variables " +
"are no longer supported: #{$old-variables-in-use}." +
"Details: http://compass-style.org/help/documentation/tuning-vendor-prefixes/"
}
@return $old-variables-in-use;
}
// @private
@function warn-about-pie-removal() {
@if global-variable-exists(experimental-support-for-pie) {
@warn "Compass no longer supports css3pie.";
}
@return true;
}
// Enable browser support debugging within the content block.
// Or you can enable it for the whole stylesheet by setting `$debug-browser-support` to true.
@mixin with-browser-support-debugging {
$current-status: $debug-browser-support;
$debug-browser-support: true !global;
@content;
$debug-browser-support: $current-status !global;
}
// Set a default value if the given arglist is empty
@function set-arglist-default($arglist, $default) {
$default-index: index($arglist, default);
@if $default-index {
$arglist: set-nth($arglist, $default-index, $default)
}
@return if(length($arglist) > 0, $arglist, $default);
}
// @private
$old-variable-warnings-issued: warn-about-old-variables() !default;
// @private
$pie-removal-warning-issued: warn-about-pie-removal() !default;
// @private
@function warn-about-useless-prefix-arguments($moz: null, $webkit: null, $o: null, $khtml: null, $official: null) {
@if $moz != null or $webkit != null or $o != null or $khtml != null or $official != null {
@warn "Browser prefix arguments to this mixin are no longer used and " +
"will be removed in the next release.";
}
@return true;
}
// coerce a list to be comma delimited or make a new, empty comma delimited list.
@function comma-list($list: ()) {
@return join((), $list, comma);
}
// @private Returns the legacy value for a given box-model
// - Used by background-clip and -origin.
@function legacy-box($box) {
$box: unquote($box);
@if $box == padding-box { $box: padding; }
@if $box == border-box { $box: border; }
@if $box == content-box { $box: content; }
@return $box;
}
================================================
FILE: core/stylesheets/compass/_typography.scss
================================================
@import "typography/links";
@import "typography/lists";
@import "typography/text";
@import "typography/vertical_rhythm";
================================================
FILE: core/stylesheets/compass/_utilities.scss
================================================
@import "utilities/color";
@import "utilities/general";
@import "utilities/sprites";
@import "utilities/tables";
// deprecated
@import "typography/links";
@import "typography/lists";
@import "typography/text";
================================================
FILE: core/stylesheets/compass/css3/_animation.scss
================================================
@import "compass/support";
// The prefixed support threshold for animation.
// Defaults to the $graceful-usage-threshold.
$animation-support-threshold: $graceful-usage-threshold !default;
// Name of any animation as a string.
$default-animation-name : null !default;
// Duration of the entire animation in seconds.
$default-animation-duration : null !default;
// Delay for start of animation in seconds.
$default-animation-delay : null !default;
// The timing function(s) to be used between keyframes. [ease | linear | ease-in | ease-out | ease-in-out | cubic-bezier($number, $number, $number, $number)]
$default-animation-timing-function : null !default;
// The number of times an animation cycle is played. [infinite | $number]
$default-animation-iteration-count : null !default;
// Whether or not the animation should play in reverse on alternate cycles. [normal | alternate]
$default-animation-direction : null !default;
// What values are applied by the animation outside the time it is executing. [none | forwards | backwards | both]
$default-animation-fill-mode : null !default;
// Whether the animation is running or paused. [running | paused]
$default-animation-play-state : null !default;
// Create a named animation sequence that can be applied to elements later.
//
// $name - The name of your animation.
// @content - The keyframes of the animation.
@mixin keyframes($name, $deprecated-prefixes...) {
$warned: warn-about-useless-prefix-arguments($deprecated-prefixes...);
@include with-each-prefix(css-animation, $animation-support-threshold) {
// It would be nice if we could dynamically construct directive names.
@if $current-prefix == -moz { @-moz-keyframes #{$name} { @content; } }
@if $current-prefix == -webkit { @-webkit-keyframes #{$name} { @content; } }
@if $current-prefix == -o { @-o-keyframes #{$name} { @content; } }
@if $current-prefix == -ms { @-ms-keyframes #{$name} { @content; } }
@if $current-prefix == null { @keyframes #{$name} { @content; } }
}
}
// @private
@mixin animation-properties($properties) {
@include prefixed-properties(css-animation, $animation-support-threshold, $properties);
}
// Apply any number of animation names.
@mixin animation-name($name...) {
$name: set-arglist-default($name, $default-animation-name);
@include animation-properties((animation-name: $name));
}
// Apply any number of animation durations.
@mixin animation-duration($duration...) {
$duration: set-arglist-default($duration, $default-animation-duration);
@include animation-properties((animation-duration: $duration));
}
// Apply any number of animation delays.
@mixin animation-delay($delay...) {
$delay: set-arglist-default($delay, $default-animation-delay);
@include animation-properties((animation-delay: $delay));
}
// Apply any number of animation timing functions.
@mixin animation-timing-function($function...) {
$function: set-arglist-default($function, $default-animation-timing-function);
@include animation-properties((animation-timing-function: $function));
}
// Apply any number of animation iteration counts.
@mixin animation-iteration-count($count...) {
$count: set-arglist-default($count, $default-animation-iteration-count);
@include animation-properties((animation-iteration-count: $count));
}
// Apply any number of animation directions.
@mixin animation-direction($direction...) {
$direction: set-arglist-default($direction, $default-animation-direction);
@include animation-properties((animation-direction: $direction));
}
// Apply any number of animation fill modes.
@mixin animation-fill-mode($mode...) {
$mode: set-arglist-default($mode, $default-animation-fill-mode);
@include animation-properties((animation-fill-mode: $mode));
}
// Apply any number of animation play states.
@mixin animation-play-state($state...) {
$state: set-arglist-default($state, $default-animation-play-state);
@include animation-properties((animation-play-state: $state));
}
// @private
@function default-animation() {
@return compact($default-animation-name
$default-animation-duration
$default-animation-timing-function
$default-animation-delay
$default-animation-iteration-count
$default-animation-direction
$default-animation-fill-mode
$default-animation-play-state);
}
// Shortcut to apply any number of animations to an element, with all the settings.
//
// $animation... : Name and settings. [ | default]
@mixin animation($animation...) {
$animation: if(length($animation) > 0, $animation, default-animation());
@include animation-properties((animation: $animation));
}
================================================
FILE: core/stylesheets/compass/css3/_appearance.scss
================================================
// Appearance
@import "compass/support";
// Change the appearance for Mozilla, Webkit and possibly the future.
// The appearance property is currently not present in any newer CSS specification.
//
// There is no official list of accepted values, but you might check these source:
//
// * [Mozilla](https://developer.mozilla.org/en/CSS/-moz-appearance)
// * [Webkit](http://code.google.com/p/webkit-mirror/source/browse/Source/WebCore/css/CSSValueKeywords.in?spec=svnf1aea559dcd025a8946aa7da6e4e8306f5c1b604&r=63c7d1af44430b314233fea342c3ddb2a052e365)
// (search for 'appearance' within the page)
@mixin appearance($appearance) {
// There is no caniuse tracking for appearance.
$appearance: unquote($appearance);
@include with-prefix(-moz) { -moz-appearance: $appearance; }
@include with-prefix(-webkit) { -webkit-appearance: $appearance; }
}
================================================
FILE: core/stylesheets/compass/css3/_background-clip.scss
================================================
// Background Clip
@import "compass/support";
// The the user threshold for background-clip support. Defaults to `$critical-usage-threshold`
$background-clip-support-threshold: $critical-usage-threshold !default;
// The default border-box model: [border-box | padding-box | content-box]
$default-background-clip: padding-box !default;
// Clip the background (image and color) at the edge of the padding, border, or content.
// $clip... : [padding-box | border-box | content-box]
@mixin background-clip($clip...) {
$output: ();
$deprecated: ();
@if (length($clip) > 0) {
@each $layer in $clip {
$output: append($output, unquote($layer), comma);
$deprecated: append($deprecated, legacy-box($layer), comma);
}
} @else {
$output: $default-background-clip;
$deprecated: legacy-box($default-background-clip);
}
@include with-each-prefix(background-img-opts, $background-clip-support-threshold) {
@if $current-prefix == -moz or $current-prefix == -webkit {
// Legacy versions of Mozilla support a different syntax, prefixed.
@include prefix-prop(background-clip, $deprecated);
} @else {
@include prefix-prop(background-clip, $output);
}
}
}
================================================
FILE: core/stylesheets/compass/css3/_background-origin.scss
================================================
// Background Origin
@import "compass/support";
// The the user threshold for background-origin support. Defaults to `$critical-usage-threshold`
$background-origin-threshold: $critical-usage-threshold !default;
// The default background-origin: [border-box | padding-box | content-box]
$default-background-origin: content-box !default;
// Set the origin of the background (image and color) at the edge of the padding, border, or content.
//
// $origin... : [padding-box | border-box | content-box]
@mixin background-origin($origin...) {
$output: ();
$deprecated: ();
@if (length($origin) > 0) {
@each $layer in $origin {
$output: append($output, unquote($layer), comma);
$deprecated: append($deprecated, legacy-box($layer), comma);
}
} @else {
$output: $default-background-origin;
$deprecated: legacy-box($default-background-origin);
}
@include with-each-prefix(background-img-opts, $background-origin-threshold) {
@if $current-prefix == -moz or $current-prefix == -webkit {
// Legacy versions of Mozilla support a different syntax, prefixed.
@include prefix-prop(background-origin, $deprecated)
} @else {
@include prefix-prop(background-origin, $output)
}
}
}
================================================
FILE: core/stylesheets/compass/css3/_background-size.scss
================================================
// Background Size
@import "compass/support";
// The the user threshold for background-clip support. Defaults to `$critical-usage-threshold`
$background-size-threshold: $critical-usage-threshold !default;
// override to change the default
$default-background-size: 100% auto !default;
// Set the size of background images using px, width and height, or percentages.
// Currently supported in: Opera, Gecko, Webkit.
//
// * percentages are relative to the background-origin (default = padding-box)
// * mixin defaults to: `$default-background-size`
@mixin background-size($size...) {
$size: set-arglist-default($size, $default-background-size);
@include prefixed-properties(background-img-opts, $background-size-threshold, (background-size: $size));
}
================================================
FILE: core/stylesheets/compass/css3/_border-radius.scss
================================================
// Border Radius
@import "compass/support";
// The the user threshold for border-radius support. Defaults to `$graceful-usage-threshold`
$border-radius-threshold: $graceful-usage-threshold !default;
// The length of a border-radius to be used by default.
$default-border-radius: 5px !default;
// Round all corners by a specific amount, defaults to value of `$default-border-radius`.
//
// When two values are passed, the first is the horizontal radius
// and the second is the vertical radius.
//
// Note: webkit does not support shorthand syntax for several corners at once.
// So in the case where you pass several values only the first will be passed to webkit.
//
// Examples:
//
// .simple { @include border-radius(4px, 4px); }
// .compound { @include border-radius(2px 5px, 3px 6px); }
// .crazy { @include border-radius(1px 3px 5px 7px, 2px 4px 6px 8px)}
//
// Which generates:
//
// .simple {
// -moz-border-radius: 4px / 4px;
// -webkit-border-radius: 4px 4px;
// border-radius: 4px / 4px; }
//
// .compound {
// -moz-border-radius: 2px 5px / 3px 6px;
// -webkit-border-radius: 2px 3px;
// border-radius: 2px 5px / 3px 6px; }
//
// .crazy {
// -moz-border-radius: 1px 3px 5px 7px / 2px 4px 6px 8px;
// -webkit-border-radius: 1px 2px;
// border-radius: 1px 3px 5px 7px / 2px 4px 6px 8px; }
@mixin border-radius($radius: $default-border-radius, $vertical-radius: false) {
@include with-each-prefix(border-radius, $border-radius-threshold) {
@if $current-prefix == -webkit {
// Legacy Webkit didn't understand the official shorthand syntax for specifying a vertical radius.
$legacy-webkit-radius: first-value-of($radius);
@if $vertical-radius { $legacy-webkit-radius: append($legacy-webkit-radius, first-value-of($vertical-radius)); }
@include prefix-prop(border-radius, $legacy-webkit-radius);
} @else {
// Official syntax for everyone else
@include prefix-prop(border-radius, if($vertical-radius, #{$radius} / #{$vertical-radius}, $radius));
}
}
}
// Round radius at position by amount.
//
// * legal values for `$vert`: `top`, `bottom`
// * legal values for `$horz`: `left`, `right`
@mixin border-corner-radius($vert, $horz, $radius: $default-border-radius) {
@include with-each-prefix(border-radius, $border-radius-threshold) {
@if $current-prefix == -moz {
// Support for mozilla's syntax for specifying a corner
@include prefix-prop("border-radius-#{$vert}#{$horz}", $radius);
} @else {
// Official syntax for everyone else
@include prefix-prop("border-#{$vert}-#{$horz}-radius", $radius);
}
}
}
// Round top-left corner only
@mixin border-top-left-radius($radius: $default-border-radius) {
@include border-corner-radius(top, left, $radius); }
// Round top-right corner only
@mixin border-top-right-radius($radius: $default-border-radius) {
@include border-corner-radius(top, right, $radius); }
// Round bottom-left corner only
@mixin border-bottom-left-radius($radius: $default-border-radius) {
@include border-corner-radius(bottom, left, $radius); }
// Round bottom-right corner only
@mixin border-bottom-right-radius($radius: $default-border-radius) {
@include border-corner-radius(bottom, right, $radius); }
// Round both top corners by amount
@mixin border-top-radius($radius: $default-border-radius) {
@include border-top-left-radius($radius);
@include border-top-right-radius($radius); }
// Round both right corners by amount
@mixin border-right-radius($radius: $default-border-radius) {
@include border-top-right-radius($radius);
@include border-bottom-right-radius($radius); }
// Round both bottom corners by amount
@mixin border-bottom-radius($radius: $default-border-radius) {
@include border-bottom-left-radius($radius);
@include border-bottom-right-radius($radius); }
// Round both left corners by amount
@mixin border-left-radius($radius: $default-border-radius) {
@include border-top-left-radius($radius);
@include border-bottom-left-radius($radius); }
================================================
FILE: core/stylesheets/compass/css3/_box-shadow.scss
================================================
// Box Shadow
@import "compass/support";
// The prefixed support threshold for box-shadow.
// Defaults to the $graceful-usage-threshold.
$box-shadow-support-threshold: $graceful-usage-threshold !default;
// The default color for box shadows
$default-box-shadow-color: #333333 !default;
// The default horizontal offset. Positive is to the right.
$default-box-shadow-h-offset: 0px !default;
// The default vertical offset. Positive is down.
$default-box-shadow-v-offset: 0px !default;
// The default blur length.
$default-box-shadow-blur: 5px !default;
// The default spread length.
$default-box-shadow-spread: null !default;
// The default shadow inset: inset or null (for standard shadow).
$default-box-shadow-inset: null !default;
@function default-box-shadow() {
@return compact(if($default-box-shadow-inset, inset, null)
$default-box-shadow-h-offset
$default-box-shadow-v-offset
$default-box-shadow-blur
$default-box-shadow-spread
$default-box-shadow-color);
}
// Provides cross-browser for Webkit, Gecko, and CSS3 box shadows
// when one or more box shadows are needed.
// Each shadow argument should adhere to the standard css3 syntax
// for the box-shadow property.
@mixin box-shadow($shadow...) {
$shadow: set-arglist-default($shadow, default-box-shadow());
@include prefixed-properties(css-boxshadow, $box-shadow-support-threshold, (box-shadow: $shadow));
}
// Provides a single cross-browser CSS box shadow for Webkit, Gecko, and CSS3.
// Includes default arguments for color, horizontal offset, vertical offset, blur length, spread length, and inset.
@mixin single-box-shadow(
$hoff : null,
$voff : null,
$blur : null,
$spread : null,
$color : null,
$inset : $default-box-shadow-inset
) {
// Handle legacy argument order
@if not ($hoff == none or $hoff == null) and type-of($hoff) != number {
@warn "The $color argument for single-box-shadow is now the 5th argument instead of the 1st.";
$tmp-color: $color;
$color: $hoff;
$hoff: $voff;
$voff: $blur;
$blur: $spread;
$spread: $tmp-color
}
// Need to set these defaults here instead of the arglist to support the above backwards compat handling
@if $hoff == null { $hoff: $default-box-shadow-h-offset; }
@if $voff == null { $hoff: $default-box-shadow-v-offset; }
@if $blur == null { $blur: $default-box-shadow-blur; }
@if $spread == null { $spread: $default-box-shadow-spread; }
@if $color == null { $color: $default-box-shadow-color; }
@if not ($inset == true or $inset == false or $inset == null or $inset == inset) {
@warn "$inset expected to be true or the inset keyword. Got #{$inset} instead. Using: inset";
}
@if $hoff == none {
@include box-shadow(none);
} @else {
$full : $hoff $voff;
@if $blur { $full: $full $blur; }
@if $spread { $full: $full $spread; }
@if $color { $full: $full $color; }
@if $inset { $full: inset $full; }
@include box-shadow($full);
}
}
================================================
FILE: core/stylesheets/compass/css3/_box-sizing.scss
================================================
// Box Sizing
@import "compass/support";
// The prefixed support threshold for box-sizing.
// Defaults to the $graceful-usage-threshold.
$box-sizing-support-threshold: $critical-usage-threshold !default;
// The default box-sizing model when no argument is provided to the box-sizing mixin: [ content-box | border-box | padding-box ]
//
// The browser default is content-box, compass defaults to border-box.
$default-box-sizing: border-box !default;
// Change the box model for Mozilla, Webkit, IE8 and the future
//
// $box-model: [ content-box | border-box | padding-box ]
@mixin box-sizing($box-model: $default-box-sizing) {
$box-model: unquote($box-model);
@include prefixed-properties(css3-boxsizing, $box-sizing-support-threshold, (box-sizing: $box-model));
}
================================================
FILE: core/stylesheets/compass/css3/_box.scss
================================================
// Flexible Box
@import "deprecated-support";
@warn "The compass/css3/box module is DEPRECATED and will be removed in the next release. Please use compass/css3/flexbox instead.";
// @private css3-feature-support variables must always include a list of five boolean values
$legacy-box-support: -moz, -webkit, not -o, -ms, not -khtml;
// Default box orientation, assuming that the user wants something less block-like
$default-box-orient : horizontal !default;
// Default box-align
$default-box-align : stretch !default;
// Default box flex
$default-box-flex : 0 !default;
// Default flex group
$default-box-flex-group : 1 !default;
// Box direction default value
$default-box-direction : normal !default;
// Default ordinal group
$default-box-ordinal-group : 1 !default;
// Default box lines
$default-box-lines : single !default;
// Default box pack
$default-box-pack : start !default;
// Apply 'display:box;' to an element.
// - must be used for any of the other flexbox mixins to work properly
@mixin display-box {
@include experimental-value(display, box, $legacy-box-support...);
}
// Box orientation [ horizontal | vertical | inline-axis | block-axis | inherit ]
@mixin box-orient($orientation: $default-box-orient) {
$orientation : unquote($orientation);
@include experimental(box-orient, $orientation, $legacy-box-support...);
}
// Box align [ start | end | center | baseline | stretch ]
@mixin box-align($alignment: $default-box-align) {
$alignment : unquote($alignment);
@include experimental(box-align, $alignment, $legacy-box-support...);
}
// Takes an int argument for box flex. Apply this to the children inside the box.
//
// For example: "div.display-box > div.child-box" would get the box flex mixin.
@mixin box-flex($flex: $default-box-flex) {
@include experimental(box-flex, $flex, $legacy-box-support...);
}
// Takes an int argument for flexible grouping
@mixin box-flex-group($group: $default-box-flex-group) {
@include experimental(box-flex-group, $group, $legacy-box-support...);
}
// Takes an int argument for ordinal grouping and rearranging the order
@mixin box-ordinal-group($group: $default-box-ordinal-group) {
@include experimental(box-ordinal-group, $group, $legacy-box-support...);
}
// Box direction [ normal | reverse | inherit ]
@mixin box-direction($direction: $default-box-direction) {
$direction: unquote($direction);
@include experimental(box-direction, $direction, $legacy-box-support...);
}
// Box lines [ single | multiple ]
@mixin box-lines($lines: $default-box-lines) {
$lines: unquote($lines);
@include experimental(box-lines, $lines, $legacy-box-support...);
}
// Box pack [ start | end | center | justify ]
@mixin box-pack($pack: $default-box-pack) {
$pack: unquote($pack);
@include experimental(box-pack, $pack, $legacy-box-support...);
}
================================================
FILE: core/stylesheets/compass/css3/_columns.scss
================================================
// Columns
@import "compass/support";
// The prefixed support threshold for columns.
// Defaults to the $critical-usage-threshold.
$multicolumn-support-threshold: $critical-usage-threshold !default;
// Specify the shorthand `columns` property.
//
// Example:
//
// @include columns(20em 2);
@mixin columns($width-and-count) {
@include prefixed-properties(multicolumn, $multicolumn-support-threshold,(
columns: $width-and-count
));
}
// Specify the number of columns
@mixin column-count($count) {
@include prefixed-properties(multicolumn, $multicolumn-support-threshold,(
column-count: $count
));
}
// Specify the gap between columns e.g. `20px`
@mixin column-gap($width) {
@include prefixed-properties(multicolumn, $multicolumn-support-threshold,(
column-gap: $width
));
}
// Specify the width of columns e.g. `100px`
@mixin column-width($width) {
@include prefixed-properties(multicolumn, $multicolumn-support-threshold,(
column-width: $width
));
}
// Specify how many columns an element should span across.
//
// * legal values are 1, all
@mixin column-span($columns) {
@include prefixed-properties(multicolumn, $multicolumn-support-threshold,(
column-span: $columns
));
}
// Specify the width of the rule between columns e.g. `1px`
@mixin column-rule-width($width) {
@include prefixed-properties(multicolumn, $multicolumn-support-threshold,(
rule-width: $width
));
}
// Specify the style of the rule between columns e.g. `dotted`.
// This works like border-style.
@mixin column-rule-style($style) {
@include prefixed-properties(multicolumn, $multicolumn-support-threshold,(
rule-style: $style
));
}
// Specify the color of the rule between columns e.g. `blue`.
// This works like border-color.
@mixin column-rule-color($color) {
@include prefixed-properties(multicolumn, $multicolumn-support-threshold,(
rule-color: $color
));
}
// Mixin encompassing all column rule properties
// For example:
//
// @include column-rule(1px, solid, #c00)
//
// Or the values can be space separated:
//
// @include column-rule(1px solid #c00)
@mixin column-rule($width, $style: null, $color: null) {
@include prefixed-properties(multicolumn, $multicolumn-support-threshold,(
column-rule: $width $style $color
));
}
// All-purpose mixin for setting column breaks.
//
// * legal values for $type : before, after, inside
// * legal values for '$value' are dependent on $type
// * when $type = before, legal values are auto, always, avoid, left, right, page, column, avoid-page, avoid-column
// * when $type = after, legal values are auto, always, avoid, left, right, page, column, avoid-page, avoid-column
// * when $type = inside, legal values are auto, avoid, avoid-page, avoid-column
//
// Examples:
// h2.before {@include column-break(before, always);}
// h2.after {@include column-break(after, always); }
// h2.inside {@include column-break(inside); }
//
// Which generates:
// h2.before {
// -webkit-column-break-before: always;
// break-before: always;}
//
// h2.after {
// -webkit-column-break-after: always;
// break-after: always; }
//
// h2.inside {
// -webkit-column-break-inside: auto;
// break-inside: auto;}
@mixin column-break($type: before, $value: auto){
@include with-each-prefix(multicolumn, $multicolumn-support-threshold) {
@if $current-prefix == -webkit {
// Webkit uses non-standard syntax
-webkit-column-break-#{$type}: $value;
} @else if $current-prefix == -moz {
// Moz uses a different non-standard syntax
-moz-page-break-#{$type}: $value;
} @else {
@include prefix-prop(break-#{$type}, $value);
}
}
}
// Mixin for setting break-before
//
// * legal values are auto, always, avoid, left, right, page, column, avoid-page, avoid-column
//
// Example:
// h2.before {@include break-before(always);}
//
// Which generates:
//
// h2.before {
// -webkit-column-break-before: always;
// break-before: always;}
@mixin break-before($value: auto){
@include column-break(before, $value);
}
@mixin column-break-before($value: auto){
@include column-break(before, $value);
@warn '"column-break-before" has been deprecated in favor of the official syntax: "break-before".';
}
// Mixin for setting break-after
//
// * legal values are auto, always, avoid, left, right, page, column, avoid-page, avoid-column
//
// Example:
// h2.after {@include break-after(always); }
//
// Which generates:
//
// h2.after {
// -webkit-column-break-after: always;
// break-after: always; }
@mixin break-after($value: auto){
@include column-break(after, $value);
}
@mixin column-break-after($value: auto){
@include column-break(after, $value);
@warn '"column-break-after" has been deprecated in favor of the official syntax: "break-after".';
}
// Mixin for setting break-inside
//
// * legal values are auto, avoid, avoid-page, avoid-column
//
// Example:
// h2.inside {@include break-inside();}
//
// Which generates:
//
// h2.inside {
// -webkit-column-break-inside: auto;
// break-inside: auto;}
@mixin break-inside($value: auto){
@include column-break(inside, $value);
}
@mixin column-break-inside($value: auto){
@include column-break(inside, $value);
@warn '"column-break-inside" has been deprecated in favor of the official syntax: "break-inside".';
}
// Mixin for setting column-span
//
// * legal values: none, all
//
// Example:
// h2.span {@include column-span();}
@mixin column-span($span: all){
@include prefixed-properties(multicolumn, $multicolumn-support-threshold,(
column-span: $span
));
}
// Mixin for setting column-fill
//
// * legal values: auto, balance
//
// Example:
// h2.fill {@include column-fill();}
@mixin column-fill($fill: balance){
@include prefixed-properties(multicolumn, $multicolumn-support-threshold,(
column-fill: $fill
));
}
================================================
FILE: core/stylesheets/compass/css3/_deprecated-support.scss
================================================
@import "compass/support";
// XXX Remove these
$experimental-support-for-mozilla: true !default;
$experimental-support-for-webkit: true !default;
$experimental-support-for-opera: true !default;
$experimental-support-for-microsoft: true !default;
$experimental-support-for-khtml: false !default;
$experimental-support-for-svg: false !default;
$legacy-support-for-ie6: true !default;
$legacy-support-for-ie7: true !default;
$legacy-support-for-ie8: true !default;
$legacy-support-for-mozilla: true !default;
$legacy-support-for-webkit: true !default;
// This mixin provides basic support for CSS3 properties and
// their corresponding experimental CSS2 properties when
// the implementations are identical except for the property
// prefix.
@mixin experimental($property, $value,
$moz : $experimental-support-for-mozilla,
$webkit : $experimental-support-for-webkit,
$o : $experimental-support-for-opera,
$ms : $experimental-support-for-microsoft,
$khtml : $experimental-support-for-khtml,
$official : true
) {
@if $webkit and $experimental-support-for-webkit { -webkit-#{$property} : $value; }
@if $khtml and $experimental-support-for-khtml { -khtml-#{$property} : $value; }
@if $moz and $experimental-support-for-mozilla { -moz-#{$property} : $value; }
@if $ms and $experimental-support-for-microsoft { -ms-#{$property} : $value; }
@if $o and $experimental-support-for-opera { -o-#{$property} : $value; }
@if $official { #{$property} : $value; }
}
// This mixin is a shortcut for applying only a single experimental value
@mixin experimental-only-for($property, $value,
$moz : false,
$webkit : false,
$o : false,
$ms : false,
$khtml : false,
$official : false
) {
@include experimental($property, $value, $moz, $webkit, $o, $ms, $khtml, $official);
}
// Same as experimental(), but for cases when the property is the same and the value is vendorized
@mixin experimental-value($property, $value,
$moz : $experimental-support-for-mozilla,
$webkit : $experimental-support-for-webkit,
$o : $experimental-support-for-opera,
$ms : $experimental-support-for-microsoft,
$khtml : $experimental-support-for-khtml,
$official : true
) {
@if $webkit and $experimental-support-for-webkit { #{$property} : -webkit-#{$value}; }
@if $khtml and $experimental-support-for-khtml { #{$property} : -khtml-#{$value}; }
@if $moz and $experimental-support-for-mozilla { #{$property} : -moz-#{$value}; }
@if $ms and $experimental-support-for-microsoft { #{$property} : -ms-#{$value}; }
@if $o and $experimental-support-for-opera { #{$property} : -o-#{$value}; }
@if $official { #{$property} : #{$value}; }
}
// @private
// Check a given support list for support of a particular browser
@function supported(
$prefix,
$support-list
) {
$keys: moz, webkit, o, ms, khtml, official;
$index: index($keys, $prefix);
@if $index {
@if $index == 6 and length($support-list) == 5 {
@return official;
} @else {
@return nth($support-list, $index);
}
} @else {
@warn 'Please pass a valid browser for $prefix: moz, webkit, o, ms, khtml, or official.';
}
}
// A debug tool for checking browser support
@mixin debug-support-matrix($experimental: true, $ie: true) {
@debug #{'$moz-'}$experimental-support-for-mozilla
#{'$webkit-'}$experimental-support-for-webkit
#{'$opera-'}$experimental-support-for-opera
#{'$microsoft-'}$experimental-support-for-microsoft
#{'$khtml-'}$experimental-support-for-khtml;
@debug #{'$ie6-'}$legacy-support-for-ie6
#{'$ie7-'}$legacy-support-for-ie7
#{'$ie8-'}$legacy-support-for-ie8;
}
// Capture the current exerimental support settings
@function capture-experimental-matrix() {
@return $experimental-support-for-mozilla
$experimental-support-for-webkit
$experimental-support-for-opera
$experimental-support-for-microsoft
$experimental-support-for-khtml;
}
// Capture the current legacy-ie support settings
@function capture-legacy-ie-matrix() {
@return $legacy-support-for-ie6
$legacy-support-for-ie7
$legacy-support-for-ie8;
}
// Capture and store support
$experimental-matrix: capture-experimental-matrix();
$legacy-ie-matrix: capture-legacy-ie-matrix();
@mixin capture-experimental-matrix {
$experimental-matrix: capture-experimental-matrix();
}
@mixin capture-legacy-ie-matrix {
$legacy-ie-matrix: capture-legacy-ie-matrix();
}
@mixin capture-support-matrix {
@include capture-experimental-matrix;
@include capture-legacy-ie-matrix;
}
// Change the experimental-support settings in specific contexts.
@mixin set-experimental-support(
$moz : false,
$webkit : false,
$o : false,
$ms : false,
$khtml : false
) {
$experimental-support-for-mozilla : $moz;
$experimental-support-for-webkit : $webkit;
$experimental-support-for-opera : $o;
$experimental-support-for-microsoft : $ms;
$experimental-support-for-khtml : $khtml;
}
@mixin capture-and-set-experimental(
$moz : false,
$webkit : false,
$o : false,
$ms : false,
$khtml : false
) {
@include capture-experimental-matrix;
@include set-experimental-support($moz, $webkit, $o, $ms, $khtml);
}
@mixin capture-and-adjust-experimental(
$moz : $experimental-support-for-mozilla,
$webkit : $experimental-support-for-webkit,
$o : $experimental-support-for-opera,
$ms : $experimental-support-for-microsoft,
$khtml : $experimental-support-for-khtml
) {
@include capture-experimental-matrix;
@include set-experimental-support($moz, $webkit, $o, $ms, $khtml);
}
// Change the legacy-support-for-ie* settings in specific contexts.
@mixin set-legacy-ie-support(
$ie6: false,
$ie7: false,
$ie8: false
) {
$legacy-support-for-ie6: $ie6;
$legacy-support-for-ie7: $ie7;
$legacy-support-for-ie8: $ie8;
}
@mixin capture-and-set-legacy-ie(
$ie6: false,
$ie7: false,
$ie8: false
) {
@include capture-legacy-ie-matrix;
@include set-legacy-ie-support($ie6, $ie7, $ie8);
}
@mixin capture-and-adjust-legacy-ie(
$ie6: $legacy-support-for-ie6,
$ie7: $legacy-support-for-ie7,
$ie8: $legacy-support-for-ie8
) {
@include capture-and-set-legacy-ie($ie6, $ie7, $ie8);
}
// Capture current browser support matrix, and set a new matrix of support.
@mixin capture-and-set-support(
$moz : false,
$webkit : false,
$o : false,
$ms : false,
$khtml : false,
$ie6 : false,
$ie7 : false,
$ie8 : false
) {
// Capture the current state
@include capture-support-matrix;
// Change support settings
@include set-experimental-support($moz, $webkit, $o, $ms, $khtml);
@include set-legacy-ie-support($ie6, $ie7, $ie8);
}
// Capture current browser support matrix, and set a new matrix of support.
@mixin capture-and-adjust-support(
$moz : $experimental-support-for-mozilla,
$webkit : $experimental-support-for-webkit,
$o : $experimental-support-for-opera,
$ms : $experimental-support-for-microsoft,
$khtml : $experimental-support-for-khtml,
$ie6 : $legacy-support-for-ie6,
$ie7 : $legacy-support-for-ie7,
$ie8 : $legacy-support-for-ie8
) {
@include capture-and-set-support($moz, $webkit, $o, $ms, $khtml, $ie6, $ie7, $ie8);
}
// This mixin allows you to change the experimental support settings for
// child (@content) styles.
@mixin with-only-support-for(
$moz : false,
$webkit : false,
$o : false,
$ms : false,
$khtml : false,
$ie6 : false,
$ie7 : false,
$ie8 : false
) {
// Capture current state
$wo-experimental-matrix : capture-experimental-matrix();
$wo-legacy-ie-matrix : capture-legacy-ie-matrix();
// Set new states
@include set-experimental-support($moz, $webkit, $o, $ms, $khtml);
@include set-legacy-ie-support($ie6, $ie7, $ie8);
// Apply styles
@content;
// Return to original support settings
@include set-experimental-support($wo-experimental-matrix...);
@include set-legacy-ie-support($wo-legacy-ie-matrix...);
}
// This mixin is a shortcut for making slight adjustments to browser support
// for child (@content) styles
@mixin adjust-support-for(
$moz : $experimental-support-for-mozilla,
$webkit : $experimental-support-for-webkit,
$o : $experimental-support-for-opera,
$ms : $experimental-support-for-microsoft,
$khtml : $experimental-support-for-khtml,
$ie6 : $legacy-support-for-ie6,
$ie7 : $legacy-support-for-ie7,
$ie8 : $legacy-support-for-ie8
) {
@include with-only-support-for($moz, $webkit, $o, $ms, $khtml, $ie6, $ie7, $ie8) {
@content;
}
}
================================================
FILE: core/stylesheets/compass/css3/_filter.scss
================================================
// Filter
@import "compass/support";
// The prefixed support threshold for css filter effects.
// Defaults to the $graceful-usage-threshold.
$filter-support-threshold: $graceful-usage-threshold !default;
// Provides cross-browser support for the upcoming (?) css3 filter property.
//
// The filter argument should adhere to the standard css3 syntax
// for the filter property.
@mixin filter($filters) {
@include prefixed-properties(css-filters, $filter-support-threshold,(
filter: $filters
));
}
// @private Apply filter-margins
@mixin apply-filter-margin($position, $width) {
@include prefixed-properties(css-filters, $filter-support-threshold,(
filter-margin-#{$position}: $width
));
}
// filter-margin-top
@mixin filter-margin-top($width) { @include apply-filter-margin(top, $width); }
// filter-margin-right
@mixin filter-margin-right($width) { @include apply-filter-margin(right, $width); }
// filter-margin-bottom
@mixin filter-margin-bottom($width) { @include apply-filter-margin(bottom, $width); }
// filter-margin-left
@mixin filter-margin-left($width) { @include apply-filter-margin(left, $width); }
// filter-margin
@mixin filter-margin($widths) {
@include prefixed-properties(css-filters, $filter-support-threshold,(
filter-margin: $widths
));
}
// color-interpolation-filters (auto | sRGB | linearRGB )
@mixin color-interpolation-filters($value) {
@include prefixed-properties(css-filters, $filter-support-threshold,(
color-interpolation-filters: $value
));
}
================================================
FILE: core/stylesheets/compass/css3/_flexbox.scss
================================================
// There are two ways to use the flexbox module.
// If you're using the final version of the spec,
// you can use the property mixins as elsewhere in
// the css3 module.
//
// You can also use the flexbox prefixing mixin `flexbox`.
// This mixin takes an optional `$version` argument which
// allows you to specify which spec version the properties
// are using so that they will be prefixed correctly.
//
// Example:
//
// .flex-column {
// /* For flexbox spec v1 */
// @include flexbox((
// display: box,
// box-orient: vertical,
// ), $version: 1);
//
// /* For flexbox spec v2 */
// @include flexbox((
// display: flexbox,
// flex-direction: column,
// ), $version: 2);
//
// /* Latest Spec */
// @include flexbox((
// display: flex,
// flex-direction: column,
// ));
// }
//
// Which compiles to:
//
// .flex-row {
// /* For flexbox spec v1 */
// display: -moz-box;
// -moz-box-orient: vertical;
// display: -webkit-box;
// -webkit-box-orient: vertical;
//
// /* For flexbox spec v2 */
// display: -ms-flexbox;
// -ms-flex-direction: column;
//
// /* Latest Spec */
// display: -webkit-flex;
// -webkit-flex-direction: column;
// display: flex;
// flex-direction: column;
// }
@import "compass/support";
$flexbox-support-threshold: $critical-usage-threshold !default;
// @private
$flexbox-capability-options: (
(full-support: true),
(partial-support: true, spec-versions: 3)
);
// This is the underlying implementation for all the other mixins in this module.
// It is the only way to access prefix support for older versions of the spec.
//
// `$properties`: map of property-value pairs that should be prefixed
// `$version1: the version of the spec to use when considering what prefix
// to appply. Defaults to the most recent (spec version 3). Only the most
// recent version of the spec outputs an unprefixed version.
@mixin flexbox($properties, $version: null) {
$capability-options: $flexbox-capability-options;
@if $version {
$capability-options: (partial-support: true, spec-versions: $version);
}
@include with-each-prefix(flexbox, $flexbox-support-threshold, $capability-options) {
// Don't output unprefixed versions when the spec version is not the final version
@if $version and $current-prefix or not $version or $version == 3 {
@each $prop, $value in $properties {
@if $prop == display {
display: prefix-identifier($value);
} @else {
@include prefix-prop($prop, $value);
}
}
}
}
}
// Values for $display are: flex (default), inline-flex
@mixin display-flex($display: flex) {
@include flexbox((display: $display));
}
// Values: row | row-reverse | column | column-reverse
@mixin flex-direction($direction) {
@include flexbox((flex-direction: $direction));
}
// Values: nowrap | wrap | wrap-reverse
@mixin flex-wrap($wrap) {
@include flexbox((flex-wrap: $wrap));
}
// Shorthand for flex-direction and flex-wrap.
@mixin flex-flow($flow) {
@include flexbox((flex-flow: $flow));
}
// Accepts an integer
@mixin order($order) {
@include flexbox((order: $order));
}
// Shorthand for flex-grow, flex-shrink and optionally flex-basis.
// Space separated, in that order.
@mixin flex($flex) {
@include flexbox((flex: $flex));
}
// Accepts a number.
@mixin flex-grow($flex-grow) {
@include flexbox((flex-grow: $flex-grow));
}
// Accepts a number.
@mixin flex-shrink($flex-shrink) {
@include flexbox((flex-shrink: $flex-shrink));
}
// Accepts any legal value for the width property.
@mixin flex-basis($flex-basis) {
@include flexbox((flex-basis: $flex-basis));
}
// Legal values: flex-start | flex-end | center | space-between | space-around
@mixin justify-content($justify-content) {
@include flexbox((justify-content: $justify-content));
}
// Legal values: flex-start | flex-end | center | baseline | stretch
@mixin align-items($align-items) {
@include flexbox((align-items: $align-items));
}
// Legal values: auto | flex-start | flex-end | center | baseline | stretch
@mixin align-self($align-self) {
@include flexbox((align-self: $align-self));
}
// Legal values: flex-start | flex-end | center | space-between | space-around | stretch
@mixin align-content($align-content) {
@include flexbox((align-content: $align-content));
}
================================================
FILE: core/stylesheets/compass/css3/_font-face.scss
================================================
@import "compass/support";
// Cross-browser support for @font-face. Supports IE, Gecko, Webkit, Opera.
//
// * $name is required, arbitrary, and what you will use in font stacks.
// * $font-files is required using font-files('relative/location', 'format').
// for best results use this order: woff, opentype/truetype, svg
// * $eot is required by IE, and is a relative location of the eot file.
// * $weight shows if the font is bold, defaults to normal
// * $style defaults to normal, might be also italic
// * For android 2.2 Compatiblity, please ensure that your web page has
// a meta viewport tag.
// * To support iOS < 4.2, an SVG file must be provided
//
// If you need to generate other formats check out the Font Squirrel
// [font generator](http://www.fontsquirrel.com/fontface/generator)
//
// In order to refer to a specific style of the font in your stylesheets as
// e.g. "font-style: italic;", you may add a couple of @font-face includes
// containing the respective font files for each style and specying
// respective the $style parameter.
// Order of the includes matters, and it is: normal, bold, italic, bold+italic.
@mixin font-face(
$name,
$font-files,
$eot: false,
$weight: false,
$style: false
) {
$iefont: unquote("#{$eot}?#iefix");
@font-face {
font-family: quote($name);
@if $eot {
src: font-url($eot);
$font-files: font-url($iefont) unquote("format('embedded-opentype')"), $font-files;
}
src: $font-files;
@if $weight {
font-weight: $weight;
}
@if $style {
font-style: $style;
}
}
}
================================================
FILE: core/stylesheets/compass/css3/_hyphenation.scss
================================================
// Mixins to support specific CSS Text Level 3 elements
@import "compass/support";
// The the user threshold for hyphens support.
// Defaults to `$graceful-usage-threshold`.
$hyphens-support-threshold: $graceful-usage-threshold !default;
// Mixin for word-break properties
// http://www.w3.org/css3-text/#word-break
// * legal values for $type : normal, keep-all, break-all
//
// Example:
// p.wordBreak {@include word-break(break-all);}
//
// Which generates:
// p.wordBreak {
// word-break: break-all;
// word-break: break-word;}
//
@mixin word-break($value: normal){
word-break: $value;
@if $value == break-all {
//Webkit handles break-all differently... as break-word
@include with-prefix(-webkit) {
word-break: break-word;
}
}
}
// Mixin for the hyphens property
//
// W3C specification: http://www.w3.org/TR/css3-text/#hyphens
// * legal values for $type : auto, manual, none
//
// Example:
// p {
// @include hyphens(auto);}
// Which generates:
// p {
// -moz-hyphens: auto;
// -webkit-hyphens: auto;
// hyphens: auto;}
//
@mixin hyphens($value: auto){
@include prefixed-properties(css-hyphens, $hyphens-support-threshold, (
hyphens: $value
));
}
// Mixin for x-browser hyphenation based on @auchenberg's post:
// Removes the need for the HTML tag
// http://blog.kenneth.io/blog/2012/03/04/word-wrapping-hypernation-using-css/
//
// Example:
// div {@include hyphenation;}
//
// Which generates:
// div {
// -ms-word-break: break-all;
// word-break: break-all;
// word-break: break-word;
// -moz-hyphens: auto;
// -webkit-hyphens: auto;
// hyphens: auto;}
//
@mixin hyphenation {
@include word-break(break-all);
@include hyphens;
}
================================================
FILE: core/stylesheets/compass/css3/_images.scss
================================================
@import "compass/support";
@import "compass/utilities/general/hacks";
$gradient-support-threshold: $graceful-usage-threshold !default;
$svg-gradient-shim-threshold: $graceful-usage-threshold !default;
$border-image-support-threshold: $graceful-usage-threshold !default;
$owg-threshold: $graceful-usage-threshold !default;
// Compass assumes you will use the official gradient syntax,
// unless otherwise instructed.
$use-legacy-gradient-syntax: false !default;
// Create a linear gradient using standard official or legacy syntax.
// This function must be included in one of the following
// image module mixins to work properly.
@function linear-gradient($angle, $details...) {
$legacy-syntax: $use-legacy-gradient-syntax;
@if type-of($angle) != 'number' {
$angle: compact($angle);
$legacy-syntax: if(index($angle, 'to'), false, true);
}
@if $legacy-syntax {
@return _linear-gradient_legacy($angle, $details...);
} @else {
@return _linear-gradient($angle, $details...);
}
}
// These browsers support svg but not gradients
// so we can shim the gradient with an inline svg file.
$browsers-supporting-svg-but-not-gradients: (ie: "9", opera: "9.5-9.6");
// These browsers require the old webkit gradient syntax
$browsers-supporting-old-webkit-gradients: (android: ("2.1", "3"));
@mixin each-gradient-prefix($values) {
@if prefixed(-svg, $values) {
@include for-legacy-browsers($browsers-supporting-svg-but-not-gradients,
$svg-gradient-shim-threshold)
{
@include with-prefix(-svg) {
@content;
}
}
}
@if prefixed(-owg, $values) {
@include for-legacy-browsers($browsers-supporting-old-webkit-gradients,
$owg-threshold)
{
@include with-prefix(-owg) {
@content;
}
}
}
@include with-each-prefix(css-gradients, $gradient-support-threshold) {
@if $current-prefix {
@if prefixed($current-prefix, $values) {
@content;
} @else if $debug-browser-support {
/* There is not a value that needs to be prefixed with #{$current-prefix} in: #{$values} */
}
} @else {
@content;
}
}
}
@mixin image-property($property, $values...) {
@include each-gradient-prefix($values) {
@if $current-prefix {
#{$property}: prefix($current-prefix, $values);
} @else {
#{$property}: $values;
}
@content;
}
}
// Background property support for vendor prefixing within values.
@mixin background($backgrounds...) {
@include image-property(background, $backgrounds...);
}
// Set any number of background layers, along with a fallback.
// The final argument will be output separately, first, as a css2 fallback.
@mixin background-with-css2-fallback($backgrounds...) {
@if length($backgrounds) > 1 or prefixed(-css2, $backgrounds) {
background: -css2(nth($backgrounds, -1));
}
@include background($backgrounds...);
}
// Background image property support for vendor prefixing within values.
@mixin background-image($images...) {
@include image-property(background-image, $images...) {
@if $current-prefix == -svg {
background-size: 100%;
}
}
}
// Emit a IE-Specific filters that renders a simple linear gradient.
// For use in IE 6 - 8. Best practice would have you apply this via a
// conditional IE stylesheet, but if you must, you should place this before
// any background-image properties that you have specified.
//
// For the `$orientation` parameter, you can pass `vertical` or `horizontal`.
@mixin filter-gradient(
$start-color,
$end-color,
$orientation: vertical
) {
@include for-legacy-browsers((ie: "8"), $gradient-support-threshold) {
@include has-layout;
$gradient-type: if($orientation == vertical, 0, 1);
filter: progid:DXImageTransform.Microsoft.gradient(gradientType=#{$gradient-type}, startColorstr='#{ie-hex-str($start-color)}', endColorstr='#{ie-hex-str($end-color)}');
}
}
// Border image property support for vendor prefixing properties and values.
@mixin border-image($value) {
@include with-each-prefix(border-image, $border-image-support-threshold) {
$border-prefix: $current-prefix;
@include each-gradient-prefix($value) {
@if $current-prefix and prefixed($current-prefix, $value) {
$legacy-value: reject($value, fill);
@include prefix-prop(border-image, prefix($current-prefix, $legacy-value), $prefix: $border-prefix);
} @else {
@include prefix-prop(border-image, $value, $prefix: $border-prefix);
}
}
}
}
// List style image property support for vendor prefixing within values.
@mixin list-style-image($image) {
@include image-property(list-style-image, $image);
}
// List style property support for vendor prefixing within values.
@mixin list-style($value) {
@include image-property(list-style, $value);
}
// content property support for vendor prefixing within values.
@mixin content($value) {
@include image-property(content, $value);
}
================================================
FILE: core/stylesheets/compass/css3/_inline-block.scss
================================================
@import "compass/support";
// The legacy support for inline-block.
// Defaults to the $graceful-usage-threshold.
$inline-block-support-threshold: $graceful-usage-threshold !default;
// Set `$inline-block-alignment` to `none` or `false` to disable the output
// of a vertical-align property in the inline-block mixin.
// Or set it to a legal value for `vertical-align` to change the default.
$inline-block-alignment: middle !default;
// Provides a cross-browser method to implement `display: inline-block;`
@mixin inline-block($alignment: $inline-block-alignment, $ie-alignment: auto) {
// legacy support for VERY old firefox
@if support-legacy-browser("firefox", "2", $threshold: $inline-block-support-threshold) {
display: -moz-inline-stack;
}
// standard
display: inline-block;
@if $alignment and $alignment != none {
vertical-align: $alignment;
}
// legacy IE support
@if support-legacy-browser("ie", "7", $threshold: $inline-block-support-threshold) {
@if $ie-alignment and $ie-alignment != none {
*vertical-align: $ie-alignment;
}
*zoom: 1;
*display: inline;
}
}
================================================
FILE: core/stylesheets/compass/css3/_opacity.scss
================================================
@import "compass/support";
// The support usage threshold for opacity. Defaults to the global
// threshold for graceful degradation.
$opacity-usage-threshold: $graceful-usage-threshold !default;
// Provides cross-browser CSS opacity. Takes a number between 0 and 1 as the argument, e.g. 0.5 for 50% opacity.
//
// @param $opacity
// A number between 0 and 1, where 0 is transparent and 1 is opaque.
@mixin opacity($opacity) {
@include for-legacy-browser("ie", "8", $threshold: $opacity-usage-threshold) {
@if $opacity == 1 {
filter: unquote("progid:DXImageTransform.Microsoft.Alpha(enabled=false)");
} @else {
filter: unquote("progid:DXImageTransform.Microsoft.Alpha(Opacity=#{round($opacity * 100)})");
}
}
opacity: $opacity;
}
// Make an element completely transparent.
@mixin transparent { @include opacity(0); }
// Make an element completely opaque.
@mixin opaque { @include opacity(1); }
================================================
FILE: core/stylesheets/compass/css3/_pie.scss
================================================
@warn "Support for CSS3Pie has been removed.";
================================================
FILE: core/stylesheets/compass/css3/_regions.scss
================================================
// Regions
@import "compass/support";
// The prefixed support threshold for css regions.
// Defaults to the $graceful-usage-threshold.
$regions-support-threshold: $graceful-usage-threshold !default;
// Webkit, IE10 and future support for [CSS Regions](http://dev.w3.org/csswg/css3-regions/)
//
// $target is a value you use to link two regions of your css.
// Give the source of your content the flow-into property,
// and give your target container the flow-from property.
//
// For a visual explanation, see the diagrams at Chris Coyier's
// [CSS-Tricks](http://css-tricks.com/content-folding/)
@mixin flow-into($target) {
$target: unquote($target);
@include prefixed-properties(css-regions, $regions-support-threshold, (flow-into: $target));
}
@mixin flow-from($target) {
$target: unquote($target);
@include prefixed-properties(css-regions, $regions-support-threshold, (flow-from: $target));
}
================================================
FILE: core/stylesheets/compass/css3/_selection.scss
================================================
@import "compass/support";
@import "compass/utilities/color";
// The prefixed support threshold for ::selection.
// Defaults to the $graceful-usage-threshold.
$selection-support-threshold: $graceful-usage-threshold !default;
// Style selected text.
//
// At this time, only two CSS properties are supported in most browsers
// during selection: color and background-color. Firefox supports the
// text-shadow property.
//
// At the stylesheet root, include the mixin within the * selector.
//
// * {
// @include selection(#fe57a1, #fff)
// }
//
// If a specific element or selector's selection is being styled
// you can use that selector instead. For example:
//
// .hot-pink {
// @include selection(#fe57a1, #fff)
// }
//
// These properties can be passed as arguments or you can set them via mixin
// content.
//
// For future-forward compatibility with other properties and aesthetic freedom,
// a mixin content block can be passed to this mixin in addition to or in place of
// passing arguments.
//
// .hot-pink {
// @include selection {
// background: #fe57a1;
// color: #fff;
// }
// }
//
// When `$background-color` is specified, but `$color` is not, this mixin
// styles the foreground color like the [contrasted
// mixin](/reference/compass/utilities/color/contrast/#mixin-contrasted). To
// specify only the background-color, you should pass an explicit `null` value
// for `$color` or use mixin content.
@mixin selection($background-color: null, $color: contrast-color($background-color)) {
@include with-each-prefix(css-selection, $selection-support-threshold) {
$selector: '';
@if $current-prefix != null {
$selector: $current-prefix + '-';
}
$selector: "&::#{$selector}selection";
#{$selector} {
color: $color;
background-color: $background-color;
@content;
}
}
}
================================================
FILE: core/stylesheets/compass/css3/_shared.scss
================================================
@warn "The compass/css3/shared module has been deprecated.
You can silence this warning by importing compass/css3/deprecated-support instead.
Please be aware that module will be removed in the next release.";
@import "deprecated-support";
================================================
FILE: core/stylesheets/compass/css3/_text-shadow.scss
================================================
// Text Shadow
@import "compass/support";
// These defaults make the arguments optional for this mixin
// If you like, set different defaults in your project
$default-text-shadow-color : #aaaaaa !default;
$default-text-shadow-h-offset : 0px !default;
$default-text-shadow-v-offset : 0px !default;
$default-text-shadow-blur : 1px !default;
$default-text-shadow-spread : false !default;
// Provides cross-browser text shadows when one or more shadows are needed.
// Each shadow argument should adhere to the standard css3 syntax for the
// text-shadow property.
//
// Note: if any shadow has a spread parameter, this will cause the mixin
// to emit the shadow declaration twice, first without the spread,
// then with the spread included. This allows you to progressively
// enhance the browsers that do support the spread parameter.
@mixin text-shadow(
$shadow...
) {
$shadow: if(length($shadow) > 0, $shadow, default);
$default: -compass-space-list(compact($default-text-shadow-h-offset $default-text-shadow-v-offset $default-text-shadow-blur $default-text-shadow-spread $default-text-shadow-color));
$shadows-without-spread: join((),(),comma);
$shadows: join((),(),comma);
$has-spread: false;
@each $layer in $shadow {
$layer: if($layer == 'default', $default, $layer);
@if length($layer) > 4 {
$has-spread: true;
$shadows-without-spread: append($shadows-without-spread, nth($layer,1) nth($layer,2) nth($layer,3) nth($layer,5));
$shadows: append($shadows, $layer);
} @else {
$shadows-without-spread: append($shadows-without-spread, $layer);
$shadows: append($shadows, $layer);
}
}
@if $has-spread {
text-shadow: $shadows-without-spread;
}
text-shadow: $shadows;
}
// Provides a single cross-browser CSS text shadow.
//
// Provides sensible defaults for the color, horizontal offset, vertical offset, blur, and spread
// according to the configuration defaults above.
@mixin single-text-shadow(
$hoff: false,
$voff: false,
$blur: false,
$spread: false,
$color: false
) {
// A lot of people think the color comes first. It doesn't.
@if type-of($hoff) == color {
$temp-color: $hoff;
$hoff: $voff;
$voff: $blur;
$blur: $spread;
$spread: $color;
$color: $temp-color;
}
// Can't rely on default assignment with multiple supported argument orders.
$hoff: if($hoff, $hoff, $default-text-shadow-h-offset);
$voff: if($voff, $voff, $default-text-shadow-v-offset);
$blur: if($blur, $blur, $default-text-shadow-blur );
$spread: if($spread, $spread, $default-text-shadow-spread );
$color: if($color, $color, $default-text-shadow-color );
// We don't need experimental support for this property.
@if $color == none or $hoff == none {
@include text-shadow(none);
} @else {
@include text-shadow(compact($hoff $voff $blur $spread $color));
}
}
================================================
FILE: core/stylesheets/compass/css3/_transform.scss
================================================
@import "compass/support";
// The the user threshold for transform support. Defaults to `$graceful-usage-threshold`
$transform-support-threshold: $graceful-usage-threshold !default;
// @doc off
// Note ----------------------------------------------------------------------
// Safari, Chrome, and Firefox all support 3D transforms. However,
// only in the most recent builds. You should also provide fallback 2d support for
// Opera and IE. IE10 is slated to have 3d enabled, but is currently unreleased.
// To make that easy, all 2D transforms include an browser-targeting toggle ($only3d)
// to switch between the two support lists. The toggle defaults to 'false' (2D),
// and also accepts 'true' (3D). Currently the lists are as follows:
// 2D: Mozilla, Webkit, Opera, Official
// 3D: Webkit, Firefox.
// Available Transforms ------------------------------------------------------
// - Scale (2d and 3d)
// - Rotate (2d and 3d)
// - Translate (2d and 3d)
// - Skew (2d only)
// Transform Parameters ------------------------------------------------------
// - Transform Origin (2d and 3d)
// - Perspective (3d)
// - Perspective Origin (3d)
// - Transform Style (3d)
// - Backface Visibility (3d)
// Mixins --------------------------------------------------------------------
// transform-origin
// - shortcuts: transform-origin2d, transform-origin3d
// - helpers: apply-origin
// transform
// - shortcuts: transform2d, transform3d
// - helpers: simple-transform, create-transform
// perspective
// - helpers: perspective-origin
// transform-style
// backface-visibility
// scale
// - shortcuts: scaleX, scaleY, scaleZ, scale3d
// rotate
// - shortcuts: rotateX, rotateY, rotate3d
// translate
// - shortcuts: translateX, translateY, translateZ, translate3d
// skew
// - shortcuts: skewX, skewY
// Defaults ------------------------------------------------------------------
// @doc on
// The default x-origin for transforms
$default-origin-x : 50% !default;
// The default y-origin for transforms
$default-origin-y : 50% !default;
// The default z-origin for transforms
$default-origin-z : 50% !default;
// The default x-multiplier for scaling
$default-scale-x : 1.25 !default;
// The default y-multiplier for scaling
$default-scale-y : $default-scale-x !default;
// The default z-multiplier for scaling
$default-scale-z : $default-scale-x !default;
// The default angle for rotations
$default-rotate : 45deg !default;
// The default x-vector for the axis of 3d rotations
$default-vector-x : 1 !default;
// The default y-vector for the axis of 3d rotations
$default-vector-y : 1 !default;
// The default z-vector for the axis of 3d rotations
$default-vector-z : 1 !default;
// The default x-length for translations
$default-translate-x : 1em !default;
// The default y-length for translations
$default-translate-y : $default-translate-x !default;
// The default z-length for translations
$default-translate-z : $default-translate-x !default;
// The default x-angle for skewing
$default-skew-x : 5deg !default;
// The default y-angle for skewing
$default-skew-y : 5deg !default;
// **Transform-origin**
// Transform-origin sent as a complete string
//
// @include apply-origin( origin [, 3D-only ] )
//
// where 'origin' is a space separated list containing 1-3 (x/y/z) coordinates
// in percentages, absolute (px, cm, in, em etc..) or relative
// (left, top, right, bottom, center) units
//
// @param only3d Set this to true to only apply this
// mixin where browsers have 3D support.
@mixin apply-origin($origin, $only3d) {
$capability: if($only3d or length($origin) > 2, transforms3d, transforms2d);
@include prefixed-properties($capability, $transform-support-threshold, (
transform-origin: $origin
));
}
// Transform-origin sent as individual arguments:
//
// @include transform-origin( [ origin-x, origin-y, origin-z, 3D-only ] )
//
// where the 3 'origin-' arguments represent x/y/z coordinates.
//
// **NOTE:** setting z coordinates triggers 3D support list, leave false for 2D support
@mixin transform-origin(
$origin-x: $default-origin-x,
$origin-y: $default-origin-y,
$origin-z: false,
$only3d: if($origin-z, true, false)
) {
$origin: unquote('');
@if $origin-x or $origin-y or $origin-z {
@if $origin-x { $origin: $origin-x; } @else { $origin: 50%; }
@if $origin-y { $origin: $origin $origin-y; } @else { @if $origin-z { $origin: $origin 50%; }}
@if $origin-z { $origin: $origin $origin-z; }
@include apply-origin($origin, $only3d);
}
}
// Transform sent as a complete string:
//
// @include transform( transforms [, 3D-only ] )
//
// where 'transforms' is a space separated list of all the transforms to be applied.
@mixin transform(
$transform,
$only3d: false
) {
$capability: if($only3d, transforms3d, transforms2d);
@include prefixed-properties($capability, $transform-support-threshold, (
transform: $transform
));
}
// Shortcut to target all browsers with 2D transform support
@mixin transform2d($trans) {
@include transform($trans, false);
}
// Shortcut to target only browsers with 3D transform support
@mixin transform3d($trans) {
@include transform($trans, true);
}
// @doc off
// 3D Parameters -------------------------------------------------------------
// @doc on
// Set the perspective of 3D transforms on the children of an element:
//
// @include perspective( perspective )
//
// where 'perspective' is a unitless number representing the depth of the
// z-axis. The higher the perspective, the more exaggerated the foreshortening.
// values from 500 to 1000 are more-or-less "normal" - a good starting-point.
@mixin perspective($p) {
@include prefixed-properties(transforms3d, $transform-support-threshold, (
perspective: $p
));
}
// Set the origin position for the perspective
//
// @include perspective-origin(origin-x [origin-y])
//
// where the two arguments represent x/y coordinates
@mixin perspective-origin($origin: 50%) {
@include prefixed-properties(transforms3d, $transform-support-threshold, (
perspective-origin: $origin
));
}
// Determine whether a 3D objects children also live in the given 3D space
//
// @include transform-style( [ style ] )
//
// where `style` can be either `flat` or `preserve-3d`.
// Browsers default to `flat`, mixin defaults to `preserve-3d`.
@mixin transform-style($style: preserve-3d) {
@include prefixed-properties(transforms3d, $transform-support-threshold, (
transform-style: $style
));
}
// Determine the visibility of an element when it's back is turned
//
// @include backface-visibility( [ visibility ] )
//
// where `visibility` can be either `visible` or `hidden`.
// Browsers default to visible, mixin defaults to hidden
@mixin backface-visibility($visibility: hidden) {
@include prefixed-properties(transforms3d, $transform-support-threshold, (
backface-visibility: $visibility
));
}
// @doc off
// Transform Partials --------------------------------------------------------
// These work well on their own, but they don't add to each other, they override.
// Use along with transform parameter mixins to adjust origin, perspective and style
// ---------------------------------------------------------------------------
// Scale ---------------------------------------------------------------------
// @doc on
// Scale an object along the x and y axis:
//
// @include scale( [ scale-x, scale-y, perspective, 3D-only ] )
//
// where the 'scale-' arguments are unitless multipliers of the x and y dimensions
// and perspective, which works the same as the stand-alone perspective property/mixin
// but applies to the individual element (multiplied with any parent perspective)
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin scale(
$scale-x: $default-scale-x,
$scale-y: $scale-x,
$perspective: false,
$only3d: false
) {
$trans: scale($scale-x, $scale-y);
@if $perspective { $trans: perspective($perspective) $trans; }
@include transform($trans, $only3d);
}
// Scale an object along the x axis
// @include scaleX( [ scale-x, perspective, 3D-only ] )
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin scaleX(
$scale: $default-scale-x,
$perspective: false,
$only3d: false
) {
$trans: scaleX($scale);
@if $perspective { $trans: perspective($perspective) $trans; }
@include transform($trans, $only3d);
}
// Scale an object along the y axis
// @include scaleY( [ scale-y, perspective, 3D-only ] )
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin scaleY(
$scale: $default-scale-y,
$perspective: false,
$only3d: false
) {
$trans: scaleY($scale);
@if $perspective { $trans: perspective($perspective) $trans; }
@include transform($trans, $only3d);
}
// Scale an object along the z axis
// @include scaleZ( [ scale-z, perspective ] )
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin scaleZ(
$scale: $default-scale-z,
$perspective: false
) {
$trans: scaleZ($scale);
@if $perspective { $trans: perspective($perspective) $trans; }
@include transform3d($trans);
}
// Scale and object along all three axis
// @include scale3d( [ scale-x, scale-y, scale-z, perspective ] )
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin scale3d(
$scale-x: $default-scale-x,
$scale-y: $default-scale-y,
$scale-z: $default-scale-z,
$perspective: false
) {
$trans: scale3d($scale-x, $scale-y, $scale-z);
@if $perspective { $trans: perspective($perspective) $trans; }
@include transform3d($trans);
}
// @doc off
// Rotate --------------------------------------------------------------------
// @doc on
// Rotate an object around the z axis (2D)
// @include rotate( [ rotation, perspective, 3D-only ] )
// where 'rotation' is an angle set in degrees (deg) or radian (rad) units
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin rotate(
$rotate: $default-rotate,
$perspective: false,
$only3d: false
) {
$trans: rotate($rotate);
@if $perspective { $trans: perspective($perspective) $trans; }
@include transform($trans, $only3d);
}
// A longcut for 'rotate' in case you forget that 'z' is implied
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin rotateZ(
$rotate: $default-rotate,
$perspective: false,
$only3d: false
) {
@include rotate($rotate, $perspective, $only3d);
}
// Rotate an object around the x axis (3D)
// @include rotateX( [ rotation, perspective ] )
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin rotateX(
$rotate: $default-rotate,
$perspective: false
) {
$trans: rotateX($rotate);
@if $perspective { $trans: perspective($perspective) $trans; }
@include transform3d($trans);
}
// Rotate an object around the y axis (3D)
// @include rotate( [ rotation, perspective ] )
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin rotateY(
$rotate: $default-rotate,
$perspective: false
) {
$trans: rotateY($rotate);
@if $perspective { $trans: perspective($perspective) $trans; }
@include transform3d($trans);
}
// Rotate an object around an arbitrary axis (3D)
// @include rotate( [ vector-x, vector-y, vector-z, rotation, perspective ] )
// where the 'vector-' arguments accept unitless numbers.
// These numbers are not important on their own, but in relation to one another
// creating an axis from your transform-origin, along the axis of Xx = Yy = Zz.
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin rotate3d(
$vector-x: $default-vector-x,
$vector-y: $default-vector-y,
$vector-z: $default-vector-z,
$rotate: $default-rotate,
$perspective: false
) {
$trans: rotate3d($vector-x, $vector-y, $vector-z, $rotate);
@if $perspective { $trans: perspective($perspective) $trans; }
@include transform3d($trans);
}
// @doc off
// Translate -----------------------------------------------------------------
// @doc on
// Move an object along the x or y axis (2D)
// @include translate( [ translate-x, translate-y, perspective, 3D-only ] )
// where the 'translate-' arguments accept any distance in percentages or absolute (px, cm, in, em etc..) units.
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin translate(
$translate-x: $default-translate-x,
$translate-y: $default-translate-y,
$perspective: false,
$only3d: false
) {
$trans: translate($translate-x, $translate-y);
@if $perspective { $trans: perspective($perspective) $trans; }
@include transform($trans, $only3d);
}
// Move an object along the x axis (2D)
// @include translate( [ translate-x, perspective, 3D-only ] )
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin translateX(
$trans-x: $default-translate-x,
$perspective: false,
$only3d: false
) {
$trans: translateX($trans-x);
@if $perspective { $trans: perspective($perspective) $trans; }
@include transform($trans, $only3d);
}
// Move an object along the y axis (2D)
// @include translate( [ translate-y, perspective, 3D-only ] )
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin translateY(
$trans-y: $default-translate-y,
$perspective: false,
$only3d: false
) {
$trans: translateY($trans-y);
@if $perspective { $trans: perspective($perspective) $trans; }
@include transform($trans, $only3d);
}
// Move an object along the z axis (3D)
// @include translate( [ translate-z, perspective ] )
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin translateZ(
$trans-z: $default-translate-z,
$perspective: false
) {
$trans: translateZ($trans-z);
@if $perspective { $trans: perspective($perspective) $trans; }
@include transform3d($trans);
}
// Move an object along the x, y and z axis (3D)
// @include translate( [ translate-x, translate-y, translate-z, perspective ] )
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin translate3d(
$translate-x: $default-translate-x,
$translate-y: $default-translate-y,
$translate-z: $default-translate-z,
$perspective: false
) {
$trans: translate3d($translate-x, $translate-y, $translate-z);
@if $perspective { $trans: perspective($perspective) $trans; }
@include transform3d($trans);
}
// @doc off
// Skew ----------------------------------------------------------------------
// @doc on
// Skew an element:
//
// @include skew( [ skew-x, skew-y, 3D-only ] )
//
// where the 'skew-' arguments accept css angles in degrees (deg) or radian (rad) units.
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin skew(
$skew-x: $default-skew-x,
$skew-y: $default-skew-y,
$only3d: false
) {
$trans: skew($skew-x, $skew-y);
@include transform($trans, $only3d);
}
// Skew an element along the x axiz
//
// @include skew( [ skew-x, 3D-only ] )
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin skewX(
$skew-x: $default-skew-x,
$only3d: false
) {
$trans: skewX($skew-x);
@include transform($trans, $only3d);
}
// Skew an element along the y axis
//
// @include skew( [ skew-y, 3D-only ] )
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin skewY(
$skew-y: $default-skew-y,
$only3d: false
) {
$trans: skewY($skew-y);
@include transform($trans, $only3d);
}
// Full transform mixins
// For settings any combination of transforms as arguments
// These are complex and not highly recommended for daily use. They are mainly
// here for backward-compatibility purposes.
//
// * they include origin adjustments
// * scale takes a multiplier (unitless), rotate and skew take degrees (deg)
//
// **Note** This mixin cannot be combined with other transform mixins.
@mixin create-transform(
$perspective: false,
$scale-x: false,
$scale-y: false,
$scale-z: false,
$rotate-x: false,
$rotate-y: false,
$rotate-z: false,
$rotate3d: false,
$trans-x: false,
$trans-y: false,
$trans-z: false,
$skew-x: false,
$skew-y: false,
$origin-x: false,
$origin-y: false,
$origin-z: false,
$only3d: false
) {
$trans: unquote("");
// perspective
@if $perspective { $trans: perspective($perspective) ; }
// scale
@if $scale-x and $scale-y {
@if $scale-z { $trans: $trans scale3d($scale-x, $scale-y, $scale-z); }
@else { $trans: $trans scale($scale-x, $scale-y); }
} @else {
@if $scale-x { $trans: $trans scaleX($scale-x); }
@if $scale-y { $trans: $trans scaleY($scale-y); }
@if $scale-z { $trans: $trans scaleZ($scale-z); }
}
// rotate
@if $rotate-x { $trans: $trans rotateX($rotate-x); }
@if $rotate-y { $trans: $trans rotateY($rotate-y); }
@if $rotate-z { $trans: $trans rotateZ($rotate-z); }
@if $rotate3d { $trans: $trans rotate3d($rotate3d); }
// translate
@if $trans-x and $trans-y {
@if $trans-z { $trans: $trans translate3d($trans-x, $trans-y, $trans-z); }
@else { $trans: $trans translate($trans-x, $trans-y); }
} @else {
@if $trans-x { $trans: $trans translateX($trans-x); }
@if $trans-y { $trans: $trans translateY($trans-y); }
@if $trans-z { $trans: $trans translateZ($trans-z); }
}
// skew
@if $skew-x and $skew-y { $trans: $trans skew($skew-x, $skew-y); }
@else {
@if $skew-x { $trans: $trans skewX($skew-x); }
@if $skew-y { $trans: $trans skewY($skew-y); }
}
// apply it!
@include transform($trans, $only3d);
@include transform-origin($origin-x, $origin-y, $origin-z, $only3d);
}
// A simplified set of options
// backwards-compatible with the previous version of the 'transform' mixin
@mixin simple-transform(
$scale: false,
$rotate: false,
$trans-x: false,
$trans-y: false,
$skew-x: false,
$skew-y: false,
$origin-x: false,
$origin-y: false
) {
@include create-transform(
false,
$scale, $scale, false,
false, false, $rotate, false,
$trans-x, $trans-y, false,
$skew-x, $skew-y,
$origin-x, $origin-y, false,
false
);
}
================================================
FILE: core/stylesheets/compass/css3/_transition.scss
================================================
@import "compass/support";
// The the user threshold for transition support. Defaults to `$graceful-usage-threshold`
$transition-support-threshold: $graceful-usage-threshold !default;
// CSS Transitions
// Currently only works in Webkit.
//
// * expected in CSS3, FireFox 3.6/7 and Opera Presto 2.3
// * We'll be prepared.
//
// Including this submodule sets following defaults for the mixins:
//
// $default-transition-property : all
// $default-transition-duration : 1s
// $default-transition-function : false
// $default-transition-delay : false
//
// Override them if you like. Timing-function and delay are set to false for browser defaults (ease, 0s).
$default-transition-property: all !default;
$default-transition-duration: 1s !default;
$default-transition-function: null !default;
$default-transition-delay: null !default;
$transitionable-prefixed-values: transform, transform-origin !default;
// Checks if the value given is a unit of time.
@function is-time($value) {
@return if(type-of($value) == number, not not index(s ms, unit($value)), false);
}
// Returns `$property` with the given prefix if it is found in `$transitionable-prefixed-values`.
@function prefixed-for-transition($prefix, $property) {
@if not $prefix {
@return $property;
}
@if type-of($property) == list or type-of($property) == arglist {
$new-list: comma-list();
@each $v in $property {
$new-list: append($new-list, prefixed-for-transition($prefix, $v));
}
@return $new-list;
} @else {
@if index($transitionable-prefixed-values, $property) {
@return #{$prefix}-#{$property};
} @else {
@return $property;
}
}
}
// Returns $transition-map which includes key and values that map to a transition declaration
@function transition-map($transition) {
$transition-map: ();
@each $item in $transition {
@if is-time($item) {
@if map-has-key($transition-map, duration) {
$transition-map: map-merge($transition-map, (delay: $item));
} @else {
$transition-map: map-merge($transition-map, (duration: $item));
}
} @else if map-has-key($transition-map, property) {
$transition-map: map-merge($transition-map, (timing-function: $item));
} @else {
$transition-map: map-merge($transition-map, (property: $item));
}
}
@return $transition-map;
}
// One or more properties to transition
//
// * for multiple, use a comma-delimited list
// * also accepts "all" or "none"
@mixin transition-property($properties...) {
$properties: set-arglist-default($properties, $default-transition-property);
@include with-each-prefix(css-transitions, $transition-support-threshold) {
$props: if($current-prefix, prefixed-for-transition($current-prefix, $properties), $properties);
@include prefix-prop(transition-property, $props);
}
}
// One or more durations in seconds
//
// * for multiple, use a comma-delimited list
// * these durations will affect the properties in the same list position
@mixin transition-duration($durations...) {
$durations: set-arglist-default($durations, $default-transition-duration);
@include prefixed-properties(css-transitions, $transition-support-threshold, (
transition-duration: $durations
));
}
// One or more timing functions
//
// * [ ease | linear | ease-in | ease-out | ease-in-out | cubic-bezier(x1, y1, x2, y2)]
// * For multiple, use a comma-delimited list
// * These functions will effect the properties in the same list position
@mixin transition-timing-function($functions...) {
$functions: set-arglist-default($functions, $default-transition-function);
@include prefixed-properties(css-transitions, $transition-support-threshold, (
transition-timing-function: $functions
));
}
// One or more transition-delays in seconds
//
// * for multiple, use a comma-delimited list
// * these delays will effect the properties in the same list position
@mixin transition-delay($delays...) {
$delays: set-arglist-default($delays, $default-transition-delay);
@include prefixed-properties(css-transitions, $transition-support-threshold, (
transition-delay: $delays
));
}
// Transition all-in-one shorthand
@mixin single-transition(
$property: $default-transition-property,
$duration: $default-transition-duration,
$function: $default-transition-function,
$delay: $default-transition-delay
) {
@include transition(compact($property $duration $function $delay));
}
@mixin transition($transitions...) {
$default: (compact($default-transition-property $default-transition-duration $default-transition-function $default-transition-delay),);
$transitions: if(length($transitions) == 1 and type-of(nth($transitions, 1)) == list and list-separator(nth($transitions, 1)) == comma, nth($transitions, 1), $transitions);
$transitions: set-arglist-default($transitions, $default);
@include with-each-prefix(css-transitions, $transition-support-threshold) {
$delays: comma-list();
$transitions-without-delays: comma-list();
$transitions-with-delays: comma-list();
$has-delays: false;
// This block can be made considerably simpler at the point in time that
// we no longer need to deal with the differences in how delays are treated.
@each $transition in $transitions {
// Declare initial values for transition
$transition: transition-map($transition);
$property: map-get($transition, property);
$duration: map-get($transition, duration);
$timing-function: map-get($transition, timing-function);
$delay: map-get($transition, delay);
// Parse transition string to assign values into correct variables
$has-delays: $has-delays or $delay;
@if $current-prefix == -webkit {
// Keep a list of delays in case one is specified
$delays: append($delays, if($delay, $delay, 0s));
$transitions-without-delays: append($transitions-without-delays,
prefixed-for-transition($current-prefix, $property) $duration $timing-function);
} @else {
$transitions-with-delays: append($transitions-with-delays,
prefixed-for-transition($current-prefix, $property) $duration $timing-function $delay);
}
}
@if $current-prefix == -webkit {
@include prefix-prop(transition, $transitions-without-delays);
@if $has-delays {
@include prefix-prop(transition-delay, $delays);
}
} @else if $current-prefix {
@include prefix-prop(transition, $transitions-with-delays);
} @else {
transition: $transitions-with-delays;
}
}
}
================================================
FILE: core/stylesheets/compass/css3/_user-interface.scss
================================================
// User Interface
// This file can be expanded to handle all the user interface properties as
// they become available in browsers:
// http://www.w3.org/TR/2000/WD-css3-userint-20000216
@import "compass/support";
// The prefixed support threshold for user-select.
// Defaults to the $graceful-usage-threshold.
$userselect-support-threshold: $graceful-usage-threshold !default;
// This property controls the selection model and granularity of an element.
//
// @param $select
// [ none | text | toggle | element | elements | all | inherit ]
@mixin user-select($select) {
$select: unquote($select);
@include with-each-prefix(user-select-none, $userselect-support-threshold) {
// old Firefox used a proprietary `-moz-none` value, starting with Firefox 21 `none` behaves like `-moz-none`
// @link https://developer.mozilla.org/en-US/docs/Web/CSS/user-select
@include prefix-prop(user-select, if($current-prefix == -moz and $select == 'none', -moz-none, $select));
}
}
// The prefixed support threshold for input-placeholder.
// Defaults to the $graceful-usage-threshold.
$input-placeholder-support-threshold: $graceful-usage-threshold !default;
// Style the html5 input placeholder in browsers that support it.
//
// The styles for the input placeholder are passed as mixin content
// and the selector comes from the mixin's context.
//
// For example:
//
// #{elements-of-type(text-input)} {
// @include input-placeholder {
// color: #bfbfbf;
// font-style: italic;
// }
// }
//
// if you want to apply the placeholder styles to all elements supporting
// the `input-placeholder` pseudo class (beware of performance impacts):
//
// * {
// @include input-placeholder {
// color: #bfbfbf;
// font-style: italic;
// }
// }
@mixin input-placeholder {
@include with-each-prefix(css-placeholder, $input-placeholder-support-threshold) {
@if $current-prefix == -webkit {
&::-webkit-input-placeholder { @content; }
}
@elseif $current-prefix == -moz {
// for Firefox 19 and below
@if support-legacy-browser("firefox", "4", "19", $threshold: $input-placeholder-support-threshold) {
&:-moz-placeholder { @content; }
}
// for Firefox 20 and above
&::-moz-placeholder { @content; }
}
@elseif $current-prefix == -ms {
&:-ms-input-placeholder { @content; }
}
}
// This is not standardized yet so no official selector is generated.
}
================================================
FILE: core/stylesheets/compass/layout/_grid-background.scss
================================================
@import "compass/css3/images";
@import "compass/css3/background-size";
// Set the color of your columns
$grid-background-column-color : rgba(100, 100, 225, 0.25) !default;
// Set the color of your gutters
$grid-background-gutter-color : rgba(0, 0, 0, 0) !default;
// Set the total number of columns in your grid
$grid-background-total-columns : 24 !default;
// Set the width of your columns
$grid-background-column-width : 30px !default;
// Set the width of your gutters
$grid-background-gutter-width : 10px !default;
// Set the offset, if your columns are padded in from the container edge
$grid-background-offset : 0px !default;
// Set the color of your baseline
$grid-background-baseline-color : rgba(0, 0, 0, 0.5) !default;
// Set the height of your baseline grid
$grid-background-baseline-height : 1.5em !default;
// toggle your columns grids on and off
$show-column-grid-backgrounds : true !default;
// toggle your vertical grids on and off
$show-baseline-grid-backgrounds : true !default;
// toggle all your grids on and off
$show-grid-backgrounds : true !default;
// optionally force your grid-image to remain fluid
// no matter what units you used to declared your grid.
$grid-background-force-fluid : false !default;
// Create the gradient needed for baseline grids
@function get-baseline-gradient(
$color : $grid-background-baseline-color
) {
$gradient: linear-gradient(to top, $color 5%, rgba($color,0) 5%);
@return $gradient;
}
// Create the color-stops needed for horizontal grids
@function build-grid-background(
$total : $grid-background-total-columns,
$column : $grid-background-column-width,
$gutter : $grid-background-gutter-width,
$offset : $grid-background-offset,
$column-color : $grid-background-column-color,
$gutter-color : $grid-background-gutter-color
) {
$grid: compact();
$grid: append($grid, $gutter-color $offset, comma);
@for $i from 0 to $total {
// $a represents the start of this column, initially equal to the offset
$a: $offset;
@if $i > 0 { $a: $a + (($column + $gutter) * $i); }
// $g represents the start of this gutter, equal to $a plus one column-width
$g: $a + $column;
// $z represents the end of a gutter, equal to $g plus one gutter-width
$z: $g + $gutter;
@if (unit($a) == "%") and ($i == ($total - 1)) {
$z: 100%;
}
// and we add this column/gutter pair to our grid
$grid: join($grid, (lighten($column-color, 5%) $a, darken($column-color, 5%) $g, $gutter-color $g, $gutter-color $z));
}
@return $grid;
}
// Return the gradient needed for horizontal grids
@function get-column-gradient(
$total : $grid-background-total-columns,
$column : $grid-background-column-width,
$gutter : $grid-background-gutter-width,
$offset : $grid-background-offset,
$column-color : $grid-background-column-color,
$gutter-color : $grid-background-gutter-color,
$force-fluid : $grid-background-force-fluid
) {
$grid: unquote("");
// don't force fluid grids when they are already fluid.
@if unit($column) == "%" { $force-fluid: false; }
@if $force-fluid {
$grid: get-column-fluid-grid($total,$column,$gutter,$offset,$column-color,$gutter-color);
} @else {
$grid: build-grid-background($total,$column,$gutter,$offset,$column-color,$gutter-color);
}
// return the horizontal grid as a gradient
$gradient: linear-gradient(left, $grid);
@return $gradient;
}
// Convert a grid from fixed units into percentages.
@function get-column-fluid-grid(
$total : $grid-background-total-columns,
$column : $grid-background-column-width,
$gutter : $grid-background-gutter-width,
$offset : $grid-background-offset,
$column-color : $grid-background-column-color,
$gutter-color : $grid-background-gutter-color
) {
$context: ($column * $total) + ($gutter * ($total - 1) + ($offset * 2));
$offset: $offset / $context * 100%;
$column: $column / $context * 100%;
$gutter: $gutter / $context * 100%;
// return the horizontal grid as a set of color-stops
$grid: build-grid-background($total,$column,$gutter,$offset,$column-color,$gutter-color);
@return $grid;
}
// Add just the baseline grid to an element's background
@mixin baseline-grid-background(
$baseline : $grid-background-baseline-height,
$color : $grid-background-baseline-color
) {
@if $show-grid-backgrounds and $show-baseline-grid-backgrounds {
@include background-image(get-baseline-gradient($color));
@include background-size(100% $baseline);
background-position: left top;
}
}
// Add just the horizontal grid to an element's background
@mixin column-grid-background(
$total : $grid-background-total-columns,
$column : $grid-background-column-width,
$gutter : $grid-background-gutter-width,
$offset : $grid-background-offset,
$column-color : $grid-background-column-color,
$gutter-color : $grid-background-gutter-color,
$force-fluid : $grid-background-force-fluid
) {
@if $show-grid-backgrounds and $show-column-grid-backgrounds {
@include background-image(
get-column-gradient($total,$column,$gutter,$offset,$column-color,$gutter-color, $force-fluid)
);
background-position: left top;
}
}
// Add both horizontal and baseline grids to an element's background
@mixin grid-background(
$total : $grid-background-total-columns,
$column : $grid-background-column-width,
$gutter : $grid-background-gutter-width,
$baseline : $grid-background-baseline-height,
$offset : $grid-background-offset,
$column-color : $grid-background-column-color,
$gutter-color : $grid-background-gutter-color,
$baseline-color : $grid-background-baseline-color,
$force-fluid : $grid-background-force-fluid
) {
@if $show-grid-backgrounds {
@if $show-baseline-grid-backgrounds and $show-column-grid-backgrounds {
@include background-image(
get-baseline-gradient($baseline-color),
get-column-gradient($total,$column,$gutter,$offset,$column-color,$gutter-color, $force-fluid)
);
@include background-size(100% $baseline, auto);
background-position: left top;
} @else {
@include baseline-grid-background($baseline, $baseline-color);
@include column-grid-background($total,$column,$gutter,$offset,$column-color,$gutter-color, $force-fluid);
}
}
}
================================================
FILE: core/stylesheets/compass/layout/_sticky-footer.scss
================================================
// Based on a [blog post by Ryan Fait](http://ryanfait.com/resources/footer-stick-to-bottom-of-page/).
//
// Must be mixed into the top level of your stylesheet.
//
// Footer element must be outside of root wrapper element.
//
// Footer must be a fixed height.
@mixin sticky-footer($footer-height, $root-selector: unquote("#root"), $root-footer-selector: unquote("#root_footer"), $footer-selector: unquote("#footer")) {
html, body {
height: 100%; }
#{$root-selector} {
clear: both;
min-height: 100%;
height: auto !important;
height: 100%;
margin-bottom: -$footer-height;
#{$root-footer-selector} {
height: $footer-height; } }
#{$footer-selector} {
clear: both;
position: relative;
height: $footer-height; } }
================================================
FILE: core/stylesheets/compass/layout/_stretching.scss
================================================
// stretch element height to specified top and bottom position
@mixin stretch-y($offset-top:0, $offset-bottom:0) {
@include stretch($offset-top, false, $offset-bottom, false);
}
// stretch element width to specified left and right position
@mixin stretch-x($offset-left:0, $offset-right:0) {
@include stretch(false, $offset-right, false, $offset-left);
}
// shorthand to stretch element height and width
@mixin stretch($offset-top:0, $offset-right:0, $offset-bottom:0, $offset-left:0) {
position: absolute;
@if $offset-top { top: $offset-top; }
@if $offset-bottom { bottom: $offset-bottom; }
@if $offset-left { left: $offset-left; }
@if $offset-right { right: $offset-right; }
}
================================================
FILE: core/stylesheets/compass/reset/_utilities-legacy.scss
================================================
// Based on [Eric Meyer's reset](http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/)
// Global reset rules.
// For more specific resets, use the reset mixins provided below
//
// *Please Note*: tables still need `cellspacing="0"` in the markup.
@mixin global-reset {
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
@include reset-box-model;
@include reset-font; }
body {
@include reset-body; }
ol, ul {
@include reset-list-style; }
table {
@include reset-table; }
caption, th, td {
@include reset-table-cell; }
q, blockquote {
@include reset-quotation; }
a img {
@include reset-image-anchor-border; } }
// Reset all elements within some selector scope. To reset the selector itself,
// mixin the appropriate reset mixin for that element type as well. This could be
// useful if you want to style a part of your page in a dramatically different way.
//
// *Please Note*: tables still need `cellspacing="0"` in the markup.
@mixin nested-reset {
div, span, object, iframe, h1, h2, h3, h4, h5, h6, p,
pre, a, abbr, acronym, address, code, del, dfn, em, img,
dl, dt, dd, ol, ul, li, fieldset, form, label, legend, caption, tbody, tfoot, thead, tr {
@include reset-box-model;
@include reset-font; }
table {
@include reset-table; }
caption, th, td {
@include reset-table-cell; }
q, blockquote {
@include reset-quotation; }
a img {
@include reset-image-anchor-border; } }
// Reset the box model measurements.
@mixin reset-box-model {
margin: 0;
padding: 0;
border: 0;
outline: 0; }
// Reset the font and vertical alignment.
@mixin reset-font {
font: {
weight: inherit;
style: inherit;
size: 100%;
family: inherit; };
vertical-align: baseline; }
// Resets the outline when focus.
// For accessibility you need to apply some styling in its place.
@mixin reset-focus {
outline: 0; }
// Reset a body element.
@mixin reset-body {
line-height: 1;
color: black;
background: white; }
// Reset the list style of an element.
@mixin reset-list-style {
list-style: none; }
// Reset a table
@mixin reset-table {
border-collapse: separate;
border-spacing: 0;
vertical-align: middle; }
// Reset a table cell (`th`, `td`)
@mixin reset-table-cell {
text-align: left;
font-weight: normal;
vertical-align: middle; }
// Reset a quotation (`q`, `blockquote`)
@mixin reset-quotation {
quotes: "" "";
&:before, &:after {
content: ""; } }
// Resets the border.
@mixin reset-image-anchor-border {
border: none; }
// Unrecognized elements are displayed inline.
// This reset provides a basic reset for html5 elements
// so they are rendered correctly in browsers that don't recognize them
// and reset in browsers that have default styles for them.
@mixin reset-html5 {
#{elements-of-type(html5-block)} {
@include reset-box-model;
display: block; } }
// Resets the display of inline and block elements to their default display
// according to their tag type. Elements that have a default display that varies across
// versions of html or browser are not handled here, but this covers the 90% use case.
// Usage Example:
//
// // Turn off the display for both of these classes
// .unregistered-only, .registered-only
// display: none
// // Now turn only one of them back on depending on some other context.
// body.registered
// +reset-display(".registered-only")
// body.unregistered
// +reset-display(".unregistered-only")
@mixin reset-display($selector: "", $important: false) {
#{append-selector(elements-of-type("inline"), $selector)} {
@if $important {
display: inline !important; }
@else {
display: inline; } }
#{append-selector(elements-of-type("block"), $selector)} {
@if $important {
display: block !important; }
@else {
display: block; } } }
================================================
FILE: core/stylesheets/compass/reset/_utilities.scss
================================================
// Based on [Eric Meyer's reset 2.0](http://meyerweb.com/eric/tools/css/reset/index.html)
// Global reset rules.
// For more specific resets, use the reset mixins provided below
@mixin global-reset {
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
@include reset-box-model;
@include reset-font; }
// Unlike Eric's original reset, we reset the html element to be compatible
// with the vertical rhythm mixins.
html {
@include reset-body; }
ol, ul {
@include reset-list-style; }
table {
@include reset-table; }
caption, th, td {
@include reset-table-cell; }
q, blockquote {
@include reset-quotation; }
a img {
@include reset-image-anchor-border; }
@include reset-html5; }
// Reset all elements within some selector scope. To reset the selector itself,
// mixin the appropriate reset mixin for that element type as well. This could be
// useful if you want to style a part of your page in a dramatically different way.
@mixin nested-reset {
div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
@include reset-box-model;
@include reset-font; }
table {
@include reset-table; }
caption, th, td {
@include reset-table-cell; }
q, blockquote {
@include reset-quotation; }
a img {
@include reset-image-anchor-border; } }
// Reset the box model measurements.
@mixin reset-box-model {
margin: 0;
padding: 0;
border: 0; }
// Reset the font and vertical alignment.
@mixin reset-font {
font: inherit;
font-size: 100%;
vertical-align: baseline; }
// Resets the outline when focus.
// For accessibility you need to apply some styling in its place.
@mixin reset-focus {
outline: 0; }
// Reset a body element.
@mixin reset-body {
line-height: 1; }
// Reset the list style of an element.
@mixin reset-list-style {
list-style: none; }
// Reset a table
@mixin reset-table {
border-collapse: collapse;
border-spacing: 0; }
// Reset a table cell (`th`, `td`)
@mixin reset-table-cell {
text-align: left;
font-weight: normal;
vertical-align: middle; }
// Reset a quotation (`q`, `blockquote`)
@mixin reset-quotation {
quotes: none;
&:before, &:after {
content: "";
content: none; } }
// Resets the border.
@mixin reset-image-anchor-border {
border: none; }
// Unrecognized elements are displayed inline.
// This reset provides a basic reset for block html5 elements
// so they are rendered correctly in browsers that don't recognize them
// and reset in browsers that have default styles for them.
@mixin reset-html5 {
#{elements-of-type(html5-block)} {
display: block; } }
// Resets the display of inline and block elements to their default display
// according to their tag type. Elements that have a default display that varies across
// versions of html or browser are not handled here, but this covers the 90% use case.
// Usage Example:
//
// // Turn off the display for both of these classes
// .unregistered-only, .registered-only
// display: none
// // Now turn only one of them back on depending on some other context.
// body.registered
// +reset-display(".registered-only")
// body.unregistered
// +reset-display(".unregistered-only")
@mixin reset-display($selector: "", $important: false) {
#{append-selector(elements-of-type("inline"), $selector)} {
@if $important {
display: inline !important; }
@else {
display: inline; } }
#{append-selector(elements-of-type("block"), $selector)} {
@if $important {
display: block !important; }
@else {
display: block; } } }
================================================
FILE: core/stylesheets/compass/typography/_links.scss
================================================
@import "links/hover-link";
@import "links/link-colors";
@import "links/unstyled-link";
================================================
FILE: core/stylesheets/compass/typography/_lists.scss
================================================
@import "lists/horizontal-list";
@import "lists/inline-list";
@import "lists/inline-block-list";
@import "lists/bullets";
================================================
FILE: core/stylesheets/compass/typography/_text.scss
================================================
@import "text/ellipsis";
@import "text/nowrap";
@import "text/replacement";
@import "text/force-wrap";
================================================
FILE: core/stylesheets/compass/typography/_units.scss
================================================
// @private Default font-size for all browsers
$browser-default-font-size: 16px;
// Base font size in pixels, if not already defined.
// Should be the same as the font-size of the html element.
$base-font-size: 16px !default;
// Whether to output fallback values in px when outputting rems.
$rem-with-px-fallback: true !default;
// Convert any CSS or value to any another.
//
// @param $length
// A css or value
//
// @param $to-unit
// String matching a css unit keyword, e.g. 'em', '%', etc.
//
// @param $from-context
// When converting from relative units, the absolute length (in px) to
// which $length refers (e.g. for $lengths in em units, would normally be the
// font-size of the current element).
//
// @param $to-context
// For converting to relative units, the absolute length in px to which the
// output value will refer. Defaults to the same as $from-context, since it is
// rarely needed.
@function convert-length(
$length,
$to-unit,
$from-context: $base-font-size,
$to-context: $from-context
) {
$from-unit: unit($length);
// Optimize for cases where `from` and `to` units are accidentally the same.
@if $from-unit == $to-unit { @return $length; }
// Context values must be in px so we can determine a conversion ratio for
// relative units.
@if unit($from-context) != 'px' { @warn "Paremeter $from-context must resolve to a value in pixel units."; }
@if unit($to-context) != 'px' { @warn "Parameter $to-context must resolve to a value in pixel units."; }
// Convert input length to pixels
$px-length: $length;
@if $from-unit != 'px' {
// Convert relative units using the from-context parameter.
@if $from-unit == 'em' { $px-length: $length * $from-context / 1em }
@else if $from-unit == 'rem' { $px-length: $length * $base-font-size / 1rem }
@else if $from-unit == '%' { $px-length: $length * $from-context / 100% }
@else if $from-unit == 'ex' { $px-length: $length * $from-context / 2ex }
// Convert absolute units using Sass' conversion table.
@else if $from-unit == 'in' or
$from-unit == 'mm' or
$from-unit == 'cm' or
$from-unit == 'pt' or
$from-unit == 'pc' { $px-length: 0px + $length }
// Certain units can't be converted.
@else if $from-unit == 'ch' or
$from-unit == 'vw' or
$from-unit == 'vh' or
$from-unit == 'vmin' {
@warn "#{$from-unit} units can't be reliably converted; Returning original value.";
@return $length;
}
@else {
@warn "#{$from-unit} is an unknown length unit. Returning original value.";
@return $length;
}
}
// Convert length in pixels to the output unit
$output-length: $px-length;
@if $to-unit != 'px' {
// Relative units
@if $to-unit == 'em' { $output-length: $px-length * 1em / $to-context }
@else if $to-unit == 'rem' { $output-length: $px-length * 1rem / $base-font-size }
@else if $to-unit == '%' { $output-length: $px-length * 100% / $to-context }
@else if $to-unit == 'ex' { $output-length: $px-length * 2ex / $to-context }
// Absolute units
@else if $to-unit == 'in' { $output-length: 0in + $px-length }
@else if $to-unit == 'mm' { $output-length: 0mm + $px-length }
@else if $to-unit == 'cm' { $output-length: 0cm + $px-length }
@else if $to-unit == 'pt' { $output-length: 0pt + $px-length }
@else if $to-unit == 'pc' { $output-length: 0pc + $px-length }
// Non-convertible units
@else if $to-unit == 'ch' or
$to-unit == 'vw' or
$to-unit == 'vh' or
$to-unit == 'vmin' {
@warn "#{$to-unit} units can't be reliably converted; Returning original value.";
@return $length;
}
@else {
@warn "#{$to-unit} is an unknown length unit. Returning original value.";
@return $length;
}
}
@return $output-length;
}
// @private Get the px/rem versions of a value.
@function rem-fallback-values($value) {
$_return: (
px: $value,
rem: $value,
);
@if type-of($value) == number and not unitless($value) {
@if unit($value) == rem {
$_return: map-merge($_return, (
px: round(convert-length($value, px)),
));
} @else if unit($value) == px {
$_return: map-merge($_return, (
px: round($value),
rem: convert-length($value, rem),
));
}
}
@return $_return;
}
// @private Get the px/rem versions of a list (or nested lists).
@function list-convert-rems($value) {
$_empty: (
px: (),
rem: (),
);
$_return: $_empty;
$_sep: null;
@if type-of($value) == list {
$_sep: list-separator($value);
@each $sub in $value {
$_this: list-convert-rems($sub);
$_return: (
px: append(map-get($_return, px), map-get($_this, px), $_sep),
rem: append(map-get($_return, rem), map-get($_this, rem), $_sep),
);
}
} @else {
$_this: rem-fallback-values($value);
$_return: map-merge($_return, $_this);
}
@return $_return;
}
// Output a given style rule containing rem values along with an (optional)
// fallback rule for older browsers (with rem values converted to px).
//
// @param $property
// The css property name.
//
// @param $values
// The value or list of values for the property.
//
// @param $use-px-fallback
// [ true | false ]
//
@mixin rem($property, $values, $use-px-fallback: $rem-with-px-fallback) {
// get converted values.
$values: list-convert-rems($values);
$px-values: map-get($values, px);
$values: map-get($values, rem);
// Use pixel fallback for browsers that don't understand rem units.
@if $use-px-fallback and $px-values != $values {
#{$property}: $px-values;
}
// Use rem values for everyone else (overrides pixel values).
#{$property}: $values;
}
================================================
FILE: core/stylesheets/compass/typography/_vertical_rhythm.scss
================================================
@import "compass/support";
@import "compass/layout/grid-background";
@import "compass/typography/units";
// The default font size for all text in pixels
$base-font-size: 16px !default;
// The distance between text baselines (vertical rhythm) in pixels.
$base-line-height: 24px !default;
// The length unit in which to output rhythm values.
// Supported values: px, em, rem. Percent units can't be used since they
// make calculating padding and margins impractical, and percentage borders are
// not valid or supported in css.
$rhythm-unit: 'em' !default;
// Whether to output fallback values in px when using rem as the rhythm-unit.
$rem-with-px-fallback: true !default;
// Default values for rhythm borders properties.
// Supports style alone eg. `solid` or list of style and color eg. `solid #aaa`;
$default-rhythm-border-width: 1px !default;
$default-rhythm-border-style: solid !default;
// Allows the `adjust-font-size-to` mixin and the `lines-for-font-size` function
// to round the line height to the nearest half line height instead of the
// nearest integral line height to avoid large spacing between lines.
$round-to-nearest-half-line: false !default;
// Ensure there is at least this many pixels
// of vertical padding above and below the text.
$min-line-padding: 2px !default;
// The leader is the amount of whitespace in a line.
// It might be useful in your calculations.
$base-leader: convert-length($base-line-height - $base-font-size, $rhythm-unit, $base-font-size);
// The half-leader is the amount of whitespace above and below a line.
// It might be useful in your calculations.
$base-half-leader: $base-leader / 2;
// @private Whether the rhythm output is in absolute units (px) or not (em, rem)
$relative-font-sizing: if($rhythm-unit == px, false, true);
// Validate units
@if unit($base-font-size) != 'px' { @warn "$base-font-size must resolve to a pixel unit."; }
@if unit($base-line-height) != 'px' { @warn "$base-line-height must resolve to a pixel unit."; }
@if $rhythm-unit != 'px' and $rhythm-unit != 'em' and $rhythm-unit != 'rem' {
@warn "$rhythm-unit must be `px`, `em` or `rem`.";
}
// Calculate rhythm units.
@function rhythm($lines: 1, $font-size: $base-font-size, $offset: 0) {
$rhythm: convert-length($lines * $base-line-height - $offset, $rhythm-unit, $font-size);
@if unit($rhythm) == px {
$rhythm: floor($rhythm);
}
@return $rhythm;
}
// Calculate the minimum multiple of rhythm units needed to contain the font-size.
@function lines-for-font-size($font-size) {
$lines: if($round-to-nearest-half-line,
ceil(2 * $font-size / $base-line-height) / 2,
ceil($font-size / $base-line-height));
// If lines are cramped include some extra lead.
@if ($lines * $base-line-height - $font-size) < ($min-line-padding * 2) {
$lines: $lines + if($round-to-nearest-half-line, 0.5, 1);
}
@return $lines;
}
// @private Outputs rhythm values. For rem units, outputs pixel fallbacks
// by default.
@mixin output-rhythm($property, $values) {
@if $rhythm-unit == rem and $rem-with-px-fallback {
@include rem($property, $values);
}
@else {
$output: ();
@each $value in $values {
@if unit($value) == px {
// Ensure all pixel values are rounded to the nearest pixel.
$output: join($output, round($value));
}
@else {
$output: join($output, $value);
}
}
#{$property}: $output;
}
}
// Establishes a font baseline for the given font-size.
@mixin establish-baseline($font-size: $base-font-size) {
$relative-size: 100% * ($font-size / $browser-default-font-size);
@if support-legacy-browser(ie, "6") and (not $relative-font-sizing) {
// IE 6 refuses to resize fonts set in pixels and it weirdly resizes fonts
// whose root is set in ems. So we set the root font size in percentages of
// the default font size, even if we are using absolute sizes elsewhere.
* html { font-size: $relative-size; }
}
html {
font-size: if($relative-font-sizing, $relative-size, $font-size);
// Webkit has a bug that prevents line-height being set in rem on ;
// To work around this and simplify output, we can set initial line-height
// in ems for all relative rhythm units, even when $rhythm-unit is `rem`.
@if $relative-font-sizing {
line-height: convert-length($base-line-height, em);
}
@else {
line-height: round($base-line-height);
}
}
}
// Resets the baseline to 1 rhythm unit
// Does not work on elements whose font-size is different from $base-font-size.
//
// @deprecated This mixin will be removed in the next release.
// Please use `adjust-leading-to(1)` instead.
@mixin reset-baseline($font-size: $base-font-size) {
@include adjust-leading-to(1, $font-size);
}
// Show a background image that can be used to debug your alignments.
// As this is a development feature, this mixin never outputs pixel fallbacks
// for rem output.
// Include the $img argument if you would rather use your own image than the
// Compass default gradient image.
@mixin debug-vertical-alignment($img: false) {
@if $img {
background: image-url($img);
}
@else {
@include baseline-grid-background(if($round-to-nearest-half-line, rhythm(1/2), rhythm(1)));
}
}
// Adjust a block to have a different font size and line height to maintain the
// rhythm. $lines specifies how many multiples of the baseline rhythm each line
// of this font should use up. It does not have to be an integer, but it
// defaults to the smallest integer that is large enough to fit the font.
// Use $from-size to adjust from a font-size other than the base font-size.
@mixin adjust-font-size-to($to-size, $lines: auto, $from-size: $base-font-size) {
$to-size: convert-length($to-size, px, $from-size);
@if $lines == auto {
$lines: lines-for-font-size($to-size);
}
@include output-rhythm(font-size, convert-length($to-size, $rhythm-unit, $from-size));
@include adjust-leading-to($lines, $to-size);
}
// Adjust a block to have different line height to maintain the rhythm.
// $lines specifies how many multiples of the baseline rhythm each line of this
// font should use up. It does not have to be an integer, but it defaults to the
// smallest integer that is large enough to fit the font.
@mixin adjust-leading-to($lines, $font-size: $base-font-size) {
@include output-rhythm(line-height, rhythm($lines, $font-size));
}
// Apply leading whitespace. The $property can be margin or padding.
@mixin leader($lines: 1, $font-size: $base-font-size, $property: margin) {
@include output-rhythm(#{$property}-top, rhythm($lines, $font-size));
}
// Apply leading whitespace as padding.
@mixin padding-leader($lines: 1, $font-size: $base-font-size) {
@include output-rhythm(padding-top, rhythm($lines, $font-size));
}
// Apply leading whitespace as margin.
@mixin margin-leader($lines: 1, $font-size: $base-font-size) {
@include output-rhythm(margin-top, rhythm($lines, $font-size));
}
// Apply trailing whitespace. The $property can be margin or padding.
@mixin trailer($lines: 1, $font-size: $base-font-size, $property: margin) {
@include output-rhythm(#{$property}-bottom, rhythm($lines, $font-size));
}
// Apply trailing whitespace as padding.
@mixin padding-trailer($lines: 1, $font-size: $base-font-size) {
@include output-rhythm(padding-bottom, rhythm($lines, $font-size));
}
// Apply trailing whitespace as margin.
@mixin margin-trailer($lines: 1, $font-size: $base-font-size) {
@include output-rhythm(margin-bottom, rhythm($lines, $font-size));
}
// Shorthand mixin to apply whitespace for top and bottom margins and padding.
@mixin rhythm(
$leader: 1,
$padding-leader: 0,
$padding-trailer: $padding-leader,
$trailer: $leader,
$font-size: $base-font-size
) {
@include leader($leader, $font-size);
@include padding-leader($padding-leader, $font-size);
@include padding-trailer($padding-trailer, $font-size);
@include trailer($trailer, $font-size);
}
// Shorthand mixin to apply whitespace for top and bottom margins.
@mixin rhythm-margins(
$leader: 1,
$trailer: $leader,
$font-size: $base-font-size
) {
@include leader($leader, $font-size);
@include trailer($trailer, $font-size);
}
// Shorthand mixin to apply whitespace for top and bottom padding.
@mixin rhythm-padding(
$padding-leader: 1,
$padding-trailer: $padding-leader,
$font-size: $base-font-size
) {
@include padding-leader($padding-leader, $font-size);
@include padding-trailer($padding-trailer, $font-size);
}
// Apply a border and whitespace to any side without destroying the vertical
// rhythm. The whitespace must be greater than the width of the border.
@mixin apply-side-rhythm-border(
$side,
$width: $default-rhythm-border-width,
$lines: 1,
$font-size: $base-font-size,
$border-style: $default-rhythm-border-style
) {
// If applying borders to all sides, use shorthand properties
$border-prop: if($side == all, border, border-#{$side});
@include output-rhythm(#{$border-prop}-width, convert-length($width, $rhythm-unit, $font-size));
#{$border-prop}-style: nth($border-style, 1);
@if type-of($border-style) == list and length($border-style) > 1 {
#{$border-prop}-color: nth($border-style, 2);
}
$padding-prop: if($side == all, padding, padding-#{$side});
@include output-rhythm(#{$padding-prop}, rhythm($lines, $font-size, $offset: $width));
}
// Apply a leading border.
// $border-style and $width are deprecated and will be removed in a future version of Compass.
@mixin leading-border(
$width: $default-rhythm-border-width,
$lines: 1,
$font-size: $base-font-size,
$border-style: $default-rhythm-border-style
) {
@include apply-side-rhythm-border(top, $width, $lines, $font-size, $border-style);
}
// Apply a trailing border.
@mixin trailing-border(
$width: $default-rhythm-border-width,
$lines: 1,
$font-size: $base-font-size,
$border-style: $default-rhythm-border-style
) {
@include apply-side-rhythm-border(bottom, $width, $lines, $font-size, $border-style);
}
// Apply both leading and trailing borders.
@mixin horizontal-borders(
$width: $default-rhythm-border-width,
$lines: 1,
$font-size: $base-font-size,
$border-style: $default-rhythm-border-style
) {
@include leading-border($width, $lines, $font-size, $border-style);
@include trailing-border($width, $lines, $font-size, $border-style);
}
// Alias for `horizontal-borders` mixin.
@mixin h-borders(
$width: $default-rhythm-border-width,
$lines: 1,
$font-size: $base-font-size,
$border-style: $default-rhythm-border-style
) {
@include horizontal-borders($width, $lines, $font-size, $border-style);
}
// Apply borders and whitespace equally to all sides.
@mixin rhythm-borders(
$width: $default-rhythm-border-width,
$lines: 1,
$font-size: $base-font-size,
$border-style: $default-rhythm-border-style
) {
@include apply-side-rhythm-border(all, $width, $lines, $font-size, $border-style);
}
================================================
FILE: core/stylesheets/compass/typography/links/_hover-link.scss
================================================
// a link that only has an underline when you hover over it
@mixin hover-link {
text-decoration: none;
&:hover, &:focus {
text-decoration: underline; } }
================================================
FILE: core/stylesheets/compass/typography/links/_link-colors.scss
================================================
// Set all the colors for a link with one mixin call.
// Order of arguments is:
//
// 1. normal
// 2. hover
// 3. active
// 4. visited
// 5. focus
//
// Those states not specified will inherit.
// Mixin to an anchor link like so:
// a
// +link-colors(#00c, #0cc, #c0c, #ccc, #cc0)
@mixin link-colors($normal, $hover: false, $active: false, $visited: false, $focus: false) {
color: $normal;
@if $visited {
&:visited {
color: $visited; } }
@if $focus {
&:focus {
color: $focus; } }
@if $hover {
&:hover {
color: $hover; } }
@if $active {
&:active {
color: $active; } } }
================================================
FILE: core/stylesheets/compass/typography/links/_unstyled-link.scss
================================================
// A link that looks and acts like the text it is contained within
@mixin unstyled-link {
color: inherit;
text-decoration: inherit;
cursor: inherit;
&:active, &:focus {
outline: none; } }
================================================
FILE: core/stylesheets/compass/typography/lists/_bullets.scss
================================================
// Turn off the bullet for an element of a list
@mixin no-bullet {
list-style-image : none;
list-style-type : none;
margin-left : 0;
}
// turns off the bullets for an entire list
@mixin no-bullets {
list-style: none;
li { @include no-bullet; }
}
// Make a list(ul/ol) have an image bullet.
//
// The mixin should be used like this for an icon that is 5x7:
//
// ul.pretty
// +pretty-bullets("my-icon.png", 5px, 7px)
//
// Additionally, if the image dimensions are not provided,
// The image dimensions will be extracted from the image itself.
//
// ul.pretty
// +pretty-bullets("my-icon.png")
//
@mixin pretty-bullets($bullet-icon, $width: image-width($bullet-icon), $height: image-height($bullet-icon), $line-height: 18px, $padding: 14px) {
margin-left: 0;
li {
padding-left: $padding;
background: image-url($bullet-icon) no-repeat ($padding - $width) / 2 ($line-height - $height) / 2;
list-style-type: none;
}
}
================================================
FILE: core/stylesheets/compass/typography/lists/_horizontal-list.scss
================================================
// Horizontal list layout module.
//
// Easy mode using simple descendant li selectors:
//
// ul.nav
// +horizontal-list
//
// Advanced mode:
// If you need to target the list items using a different selector then use
// +horizontal-list-container on your ul/ol and +horizontal-list-item on your li.
// This may help when working on layouts involving nested lists. For example:
//
// ul.nav
// +horizontal-list-container
// > li
// +horizontal-list-item
@import "bullets";
@import "compass/utilities/general/clearfix";
@import "compass/utilities/general/reset";
@import "compass/utilities/general/float";
@import "compass/support";
// Can be mixed into any selector that target a ul or ol that is meant
// to have a horizontal layout. Used to implement +horizontal-list.
@mixin horizontal-list-container {
@include reset-box-model;
@include clearfix; }
// Can be mixed into any li selector that is meant to participate in a horizontal layout.
// Used to implement +horizontal-list.
//
// :last-child is not fully supported
// see http://www.quirksmode.org/css/contents.html#t29 for the support matrix
//
// IE8 ignores rules that are included on the same line as :last-child
// see http://www.richardscarrott.co.uk/posts/view/ie8-last-child-bug for details
//
// Setting `$padding` to `false` disables the padding between list elements
@mixin horizontal-list-item($padding: 4px, $direction: left) {
@include no-bullet;
white-space: nowrap;
@include float($direction);
@if $padding {
padding: {
left: $padding;
right: $padding;
}
&:first-child #{if(support-legacy-browser("ie", "6", $threshold: $css-sel2-support-threshold), ', &.first', '')} { padding-#{$direction}: 0; }
&:last-child { padding-#{opposite-position($direction)}: 0; }
@if support-legacy-browser("ie", "7", $threshold: $css-sel2-support-threshold) {
&.last { padding-#{opposite-position($direction)}: 0; } }
}
}
// A list(ol,ul) that is layed out such that the elements are floated left and won't wrap.
// This is not an inline list.
//
// Setting `$padding` to `false` disables the padding between list elements
@mixin horizontal-list($padding: 4px, $direction: left) {
@include horizontal-list-container;
li {
@include horizontal-list-item($padding, $direction); } }
================================================
FILE: core/stylesheets/compass/typography/lists/_inline-block-list.scss
================================================
// Inline-Block list layout module.
//
// Easy mode using simple descendant li selectors:
//
// ul.nav {
// @import inline-block-list;
// }
//
// Advanced mode:
// If you need to target the list items using a different selector then use
// `@include inline-block-list-container` on your ul/ol and
// `@include inline-block-list-item` on your li. This may help when working
// on layouts involving nested lists. For example:
//
// ul.nav {
// @include inline-block-list-container;
// > li {
// @include inline-block-list-item;
// }
// }
@import "bullets";
@import "horizontal-list";
@import "compass/utilities/general/float";
@import "compass/css3/inline-block";
// Can be mixed into any selector that target a ul or ol that is meant
// to have an inline-block layout. Used to implement `inline-block-list`.
@mixin inline-block-list-container {
@include horizontal-list-container; }
// Can be mixed into any li selector that is meant to participate in a horizontal layout.
// Used to implement `inline-block-list`.
@mixin inline-block-list-item($padding: false) {
@include no-bullet;
@include inline-block;
white-space: nowrap;
@if $padding {
padding: {
left: $padding;
right: $padding;
};
}
}
// A list(ol,ul) that is layed out such that the elements are inline-block and won't wrap.
@mixin inline-block-list($padding: false) {
@include inline-block-list-container;
li {
@include inline-block-list-item($padding); } }
================================================
FILE: core/stylesheets/compass/typography/lists/_inline-list.scss
================================================
@import "compass/support";
// makes a list inline.
@mixin inline-list {
list-style-type: none;
&, & li {
margin: 0;
padding: 0;
display: inline;
}
}
// makes an inline list delimited with the passed string.
// Defaults to making a comma-separated list.
//
// Please make note of the browser support issues before using this mixin:
//
// use of `content` and `:after` is not fully supported in all browsers.
// See quirksmode for the [support matrix](http://www.quirksmode.org/css/contents.html#t15)
//
// `:last-child` is not fully supported.
// see quirksmode for the [support matrix](http://www.quirksmode.org/css/contents.html#t29).
//
// IE8 ignores rules that are included on the same line as :last-child
// see http://www.richardscarrott.co.uk/posts/view/ie8-last-child-bug for details
@mixin delimited-list($separator: ", ") {
@include inline-list;
li {
&:after { content: $separator; }
&:last-child {
&:after { content: ""; }
}
@if support-legacy-browser("ie", "7", $threshold: $css-sel2-support-threshold) {
&.last {
&:after { content: ""; }
}
}
}
}
// See [delimited-list](#mixin-delimited-list)
// @deprecated
@mixin comma-delimited-list {
@warn "comma-delimited-list is deprecated. Please use delimited-list instead.";
@include delimited-list;
}
================================================
FILE: core/stylesheets/compass/typography/text/_ellipsis.scss
================================================
@import "compass/css3/deprecated-support";
// To get full firefox support, you must install the ellipsis pattern:
//
// compass install compass/ellipsis
$use-mozilla-ellipsis-binding: false !default;
// This technique, by [Justin Maxwell](http://code404.com/), was originally
// published [here](http://mattsnider.com/css/css-string-truncation-with-ellipsis/).
// Firefox implementation by [Rikkert Koppes](http://www.rikkertkoppes.com/thoughts/2008/6/).
@mixin ellipsis($no-wrap: true) {
@if $no-wrap { white-space: nowrap; }
overflow: hidden;
@include experimental(text-overflow, ellipsis,
not -moz,
not -webkit,
-o,
-ms,
not -khtml,
official
);
@if $legacy-support-for-mozilla and $use-mozilla-ellipsis-binding {
-moz-binding: stylesheet-url(unquote("xml/ellipsis.xml#ellipsis"));
}
}
================================================
FILE: core/stylesheets/compass/typography/text/_force-wrap.scss
================================================
// Prevent long urls and text from breaking layouts
// [originally from perishablepress.com](http://perishablepress.com/press/2010/06/01/wrapping-content/)
@mixin force-wrap {
white-space: pre; // CSS 2.0
white-space: pre-wrap; // CSS 2.1
white-space: pre-line; // CSS 3.0
white-space: -pre-wrap; // Opera 4-6
white-space: -o-pre-wrap; // Opera 7
white-space: -moz-pre-wrap; // Mozilla
white-space: -hp-pre-wrap; // HP Printers
word-wrap: break-word; // IE 5+
}
================================================
FILE: core/stylesheets/compass/typography/text/_nowrap.scss
================================================
// When remembering whether or not there's a hyphen in white-space is too hard
@mixin nowrap { white-space: nowrap; }
================================================
FILE: core/stylesheets/compass/typography/text/_replacement.scss
================================================
@import "compass/support";
// Indicates the direction you prefer to move your text
// when hiding it.
//
// `left` is more robust, especially in older browsers.
// `right` seems have better runtime performance.
$hide-text-direction: left !default;
// Hides html text and replaces it with an image.
// If you use this on an inline element, you will need to change the display to block or inline-block.
// Also, if the size of the image differs significantly from the font size, you'll need to set the width and/or height.
//
// Parameters:
//
// * `img` -- the relative path from the project image directory to the image, or a url literal.
// * `x` -- the x position of the background image.
// * `y` -- the y position of the background image.
@mixin replace-text($img, $x: 50%, $y: 50%) {
@include hide-text;
background: {
@if is-url($img) {
image: $img;
} @else {
image: image-url($img);
}
repeat: no-repeat;
position: $x $y;
};
}
// Like the `replace-text` mixin, but also sets the width
// and height of the element according the dimensions of the image.
//
// If you set `$inline` to true, then an inline image (data uri) will be used.
@mixin replace-text-with-dimensions($img, $x: 50%, $y: 50%, $inline: false) {
@include replace-text(if($inline, inline-image($img), $img), $x, $y);
width: image-width($img);
height: image-height($img);
}
// Hides text in an element so you can see the background.
//
// The direction indicates how the text should be moved out of view.
//
// See `$hide-text-direction` for more information and to set this globally
// for your application.
@mixin hide-text($direction: $hide-text-direction) {
@if $direction == left {
$approximate-em-value: 12px / 1em;
$wider-than-any-screen: -9999em;
text-indent: $wider-than-any-screen * $approximate-em-value;
overflow: hidden;
text-align: left;
} @else {
// slightly wider than the box prevents issues with inline-block elements
text-indent: 110%;
white-space: nowrap;
overflow: hidden;
}
@include for-legacy-browsers((ie: "7"), $critical-usage-threshold) {
//Text transform capitalize fixes text-replacement issue when used in a