updating stripped branch to our 1.0rc. straight import.

This commit is contained in:
Paul Irish
2011-03-07 00:01:37 -08:00
parent 76305bc4a9
commit fb90b8c259
82 changed files with 10054 additions and 7809 deletions

38
.gitignore vendored
View File

@@ -1,4 +1,36 @@
.svn/
publish/
build/buildinfo.properties
# Numerous always-ignore extensions
*.diff
*.err
*.orig
*.log
*.rej
*.swo
*.swp
*.vi
*~
# OS or Editor folders
.DS_Store
.cache
.project
.settings
nbproject
thumbs.db
# Dreamweaver added files
_notes
dwsync.xml
# Komodo
*.komodoproject
.komodotools
# Folders to ignore
.hg
.svn
publish
.idea
# build script local files
build/buildinfo.properties
build/config/buildinfo.properties

313
.htaccess
View File

@@ -1,14 +1,30 @@
# Apache configuration file
# httpd.apache.org/docs/2.2/mod/quickreference.html
# Note .htaccess files are an overhead, this logic should be in your Apache config if possible
# httpd.apache.org/docs/2.2/howto/htaccess.html
# Techniques in here adapted from all over, including:
# Kroc Camen: camendesign.com/.htaccess
# perishablepress.com/press/2006/01/10/stupid-htaccess-tricks/
# Sample .htaccess file of CMS MODx: modxcms.com
###
### If you run a webserver other than apache, consider:
### github.com/paulirish/html5-boilerplate-server-configs
###
# ----------------------------------------------------------------------
# Better website experience for IE users
# ----------------------------------------------------------------------
# Force the latest IE version, in various cases when it may fall back to IE7 mode
# github.com/rails/rails/commit/123eb25#commitcomment-118920
# Use ChromeFrame if it's installed for a better experience for the poor IE folk
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
BrowserMatch MSIE ie
@@ -23,14 +39,24 @@
# Cache control is set only if mod_headers is enabled, so that's unncessary to declare
</IfModule>
# hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/
# Disabled. Uncomment to serve cross-domain ajax requests
#<IfModule mod_headers.c>
# Header set Access-Control-Allow-Origin "*"
#</IfModule>
# ----------------------------------------------------------------------
# Cross-domain AJAX requests
# ----------------------------------------------------------------------
# Serve cross-domain ajax requests, disabled.
# enable-cors.org
# code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
# <IfModule mod_headers.c>
# Header set Access-Control-Allow-Origin "*"
# </IfModule>
# ----------------------------------------------------------------------
# Webfont access
# ----------------------------------------------------------------------
# allow access from all domains for webfonts
# alternatively you could only whitelist
@@ -43,8 +69,16 @@
</FilesMatch>
# ----------------------------------------------------------------------
# Proper MIME type for all files
# ----------------------------------------------------------------------
# audio
AddType audio/ogg oga ogg
# video
AddType video/ogg ogg ogv
AddType video/ogg ogv
AddType video/mp4 mp4
AddType video/webm webm
@@ -57,23 +91,26 @@ AddEncoding gzip svgz
AddType application/vnd.ms-fontobject eot
AddType font/truetype ttf
AddType font/opentype otf
AddType font/woff woff
AddType application/x-font-woff woff
# assorted types
AddType image/vnd.microsoft.icon ico
AddType image/x-icon ico
AddType image/webp webp
AddType text/cache-manifest manifest
AddType text/cache-manifest appcache manifest
AddType text/x-component htc
AddType application/x-chrome-extension crx
AddType application/x-xpinstall xpi
AddType application/octet-stream safariextz
# allow concatenation from within specific js and css files
# ----------------------------------------------------------------------
# Allow concatenation from within specific js and css files
# ----------------------------------------------------------------------
# e.g. Inside of script.combined.js you could have
# <!--#include file="jquery-1.4.2.js" -->
# <!--#include file="jquery.idletimer.js" -->
# <!--#include file="libs/jquery-1.5.0.min.js" -->
# <!--#include file="plugins/jquery.idletimer.js" -->
# and they would be included into this single file
# this is not in use in the boilerplate as it stands. you may
@@ -88,15 +125,35 @@ AddType application/x-chrome-extension crx
# ----------------------------------------------------------------------
# gzip compression
# ----------------------------------------------------------------------
# gzip compression.
<IfModule mod_deflate.c>
# force deflate for mangled headers developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping/
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s,?\s(gzip|deflate)?|X{4,13}|~{4,13}|-{4,13})$ HAVE_Accept-Encoding
RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
</IfModule>
</IfModule>
# html, txt, css, js, json, xml, htc:
<IfModule filter_module>
FilterDeclare COMPRESS
FilterProvider COMPRESS DEFLATE resp=Content-Type /text/(html|css|javascript|plain|x(ml|-component))/
FilterProvider COMPRESS DEFLATE resp=Content-Type /application/(javascript|json|xml|x-javascript)/
FilterChain COMPRESS
FilterProtocol COMPRESS change=yes;byteranges=no
</IfModule>
<IfModule !mod_filter.c>
# Legacy versions of Apache
AddOutputFilterByType DEFLATE text/html text/plain text/css application/json
AddOutputFilterByType DEFLATE text/javascript application/javascript application/x-javascript
AddOutputFilterByType DEFLATE text/xml application/xml text/x-component
</IfModule>
# webfonts and svg:
<FilesMatch "\.(ttf|otf|eot|svg)$" >
@@ -106,6 +163,10 @@ AddType application/x-chrome-extension crx
# ----------------------------------------------------------------------
# Expires headers (for better cache control)
# ----------------------------------------------------------------------
# these are pretty far-future expires headers
# they assume you control versioning with cachebusting query params like
# <script src="application.js?20100608">
@@ -116,13 +177,12 @@ AddType application/x-chrome-extension crx
# "access plus 1 week" or so
<IfModule mod_expires.c>
Header set Cache-Control "public"
ExpiresActive on
# Perhaps better to whitelist expires rules? Perhaps.
ExpiresDefault "access plus 1 month"
# cache.manifest needs re-requests in FF 3.6 (thx Remy ~Introducing HTML5)
# cache.appcache needs re-requests in FF 3.6 (thx Remy ~Introducing HTML5)
ExpiresByType text/cache-manifest "access plus 0 seconds"
# your document html
@@ -133,12 +193,11 @@ AddType application/x-chrome-extension crx
ExpiresByType application/xml "access plus 0 seconds"
ExpiresByType application/json "access plus 0 seconds"
# rss feed
ExpiresByType application/rss+xml "access plus 1 hour"
# favicon (cannot be renamed)
ExpiresByType image/vnd.microsoft.icon "access plus 1 week"
ExpiresByType image/x-icon "access plus 1 week"
# media: images, video, audio
ExpiresByType image/gif "access plus 1 month"
@@ -150,21 +209,32 @@ AddType application/x-chrome-extension crx
ExpiresByType video/mp4 "access plus 1 month"
ExpiresByType video/webm "access plus 1 month"
# htc files (css3pie)
ExpiresByType text/x-component "access plus 1 month"
# webfonts
ExpiresByType font/truetype "access plus 1 month"
ExpiresByType font/opentype "access plus 1 month"
ExpiresByType font/woff "access plus 1 month"
ExpiresByType application/x-font-woff "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
# css and javascript
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType text/css "access plus 2 months"
ExpiresByType application/javascript "access plus 2 months"
ExpiresByType text/javascript "access plus 2 months"
<IfModule mod_headers.c>
Header append Cache-Control "public"
</IfModule>
</IfModule>
# ----------------------------------------------------------------------
# ETag removal
# ----------------------------------------------------------------------
# Since we're sending far-future expires, we don't need ETags for
# static content.
@@ -173,6 +243,24 @@ FileETag None
# ----------------------------------------------------------------------
# Stop screen flicker in IE on CSS rollovers
# ----------------------------------------------------------------------
# The following directives stop screen flicker in IE on CSS rollovers - in
# combination with the "ExpiresByType" rules for images (see above). If
# needed, un-comment the following rules.
# BrowserMatch "MSIE" brokenvary=1
# BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1
# BrowserMatch "Opera" !brokenvary
# SetEnvIf brokenvary 1 force-no-vary
# ----------------------------------------------------------------------
# Cookie setting from iframes
# ----------------------------------------------------------------------
# Allow cookies to be set from iframes (for IE only)
# If needed, uncomment and specify a path or regex in the Location directive
@@ -184,37 +272,204 @@ FileETag None
# </IfModule>
# you probably want www.example.com to forward to example.com -- shorter URLs are sexier.
# no-www.org/faq.php?q=class_b
# ----------------------------------------------------------------------
# Start rewrite engine
# ----------------------------------------------------------------------
# Turning on the rewrite engine is necessary for the following rules and features.
<IfModule mod_rewrite.c>
RewriteEngine On
</IfModule>
# ----------------------------------------------------------------------
# Suppress or force the "www." at the beginning of URLs
# ----------------------------------------------------------------------
# The same content should never be available under two different URLs - especially not with and
# without "www." at the beginning, since this can cause SEO problems (duplicate content).
# That's why you should choose one of the alternatives and redirect the other one.
# By default option 1 (no "www.") is activated. Remember: Shorter URLs are sexier.
# no-www.org/faq.php?q=class_b
# If you rather want to use option 2, just comment out all option 1 lines
# and uncomment option 2.
# IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME!
# ----------------------------------------------------------------------
# Option 1:
# Rewrite "www.domain.com -> domain.com"
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
</IfModule>
# ----------------------------------------------------------------------
# Option 2:
# To rewrite "domain.com -> www.domain.com" uncomment the following lines.
# Be aware that the following rule might not be a good idea if you
# use "real" subdomains for certain parts of your website.
# <IfModule mod_rewrite.c>
# RewriteCond %{HTTPS} !=on
# RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
# RewriteCond %{HTTP_HOST} (.+)$ [NC]
# RewriteRule ^(.*)$ http://www.%1/$1 [R=301,L]
# </IfModule>
# ----------------------------------------------------------------------
# Add/remove trailing slash to (non-file) URLs
# ----------------------------------------------------------------------
# Google treats URLs with and without trailing slashes separately.
# Forcing a trailing slash is usually preferred, but all that's really
# important is that one correctly redirects to the other.
# By default option 1 (force trailing slash) is activated.
# http://googlewebmastercentral.blogspot.com/2010/04/to-slash-or-not-to-slash.html
# http://www.alistapart.com/articles/slashforward/
# http://httpd.apache.org/docs/2.0/misc/rewriteguide.html#url Trailing Slash Problem
# ----------------------------------------------------------------------
# Option 1:
# Rewrite "domain.com/foo -> domain.com/foo/"
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/|#(.*))$
RewriteRule ^(.*)$ /$1/ [R=301,L]
</IfModule>
# ----------------------------------------------------------------------
# Option 2:
# Rewrite "domain.com/foo/ -> domain.com/foo"
#<IfModule mod_rewrite.c>
# RewriteRule ^(.*)/$ /$1 [R=301,L]
#</IfModule>
# ----------------------------------------------------------------------
# Built-in filename-based cache busting
# ----------------------------------------------------------------------
# If you're not using the build script to manage your filename version revving,
# you might want to consider enabling this, which will route requests for
# /css/all.20110203.css to /res/all.css
# To understand why this is important and a better idea than all.css?v1231,
# read: github.com/paulirish/html5-boilerplate/wiki/Version-Control-with-Cachebusting
# Uncomment to enable.
# <IfModule mod_rewrite.c>
# RewriteCond %{REQUEST_FILENAME} !-f
# RewriteCond %{REQUEST_FILENAME} !-d
# RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L]
# </IfModule>
# ----------------------------------------------------------------------
# Prevent SSL cert warnings
# ----------------------------------------------------------------------
# Rewrite secure requests properly to prevent SSL cert warnings, e.g. prevent
# https://www.domain.com when your cert only allows https://secure.domain.com
# Uncomment the following lines to use this feature.
# <IfModule mod_rewrite.c>
# RewriteCond %{SERVER_PORT} !^443
# RewriteRule (.*) https://example-domain-please-change-me.com/$1 [R=301,L]
# </IfModule>
# ----------------------------------------------------------------------
# Prevent 404 errors for non-existing redirected folders
# ----------------------------------------------------------------------
# without -MultiViews, Apache will give a 404 for a rewrite if a folder of the same name does not exist
# e.g. /blog/hello : webmasterworld.com/apache/3808792.htm
Options -MultiViews
# -Indexes will have Apache block users from browsing folders without a default document
# Options -Indexes
# ----------------------------------------------------------------------
# custom 404 page
# ----------------------------------------------------------------------
# You can add custom pages to handle 500 or 403 pretty easily, if you like.
ErrorDocument 404 /404.html
# ----------------------------------------------------------------------
# UTF-8 encoding
# ----------------------------------------------------------------------
# use utf-8 encoding for anything served text/plain or text/html
AddDefaultCharset utf-8
# force utf-8 for a number of file formats
AddCharset utf-8 .html .css .js .xml .json .rss
# We don't need to tell everyone we're apache.
ServerSignature Off
# ----------------------------------------------------------------------
# A little more security
# ----------------------------------------------------------------------
# Do we want to advertise the exact version number of Apache we're running?
# Probably not.
## This can only be enabled if used in httpd.conf - It will not work in .htaccess
# ServerTokens Prod
# "-Indexes" will have Apache block users from browsing folders without a default document
# Usually you should leave this activated, because you shouldn't allow everybody to surf through
# every folder on your server (which includes rather private places like CMS system folders).
# Options -Indexes
# Block access to "hidden" directories whose names begin with a period. This
# includes directories used by version control systems such as Subversion or Git.
<IfModule mod_rewrite.c>
RewriteRule "(^|/)\." - [F]
</IfModule>
# If your server is not already configured as such, the following directive
# should be uncommented in order to set PHP's register_globals option to OFF.
# This closes a major security hole that is abused by most XSS (cross-site
# scripting) attacks. For more information: http://php.net/register_globals
#
# IF REGISTER_GLOBALS DIRECTIVE CAUSES 500 INTERNAL SERVER ERRORS :
#
# Your server does not allow PHP directives to be set via .htaccess. In that
# case you must make this change in your php.ini file instead. If you are
# using a commercial web host, contact the administrators for assistance in
# doing this. Not all servers allow local php.ini files, and they should
# include all PHP configurations (not just this one), or you will effectively
# reset everything to PHP defaults. Consult www.php.net for more detailed
# information about setting PHP directives.
# php_flag register_globals Off

View File

@@ -1,22 +1,32 @@
<!doctype html>
<title>not found</title>
<title>Page Not Found</title>
<style>
body { text-align: center;}
h1 { font-size: 50px; }
body { font: 20px Constantia, 'Hoefler Text', "Adobe Caslon Pro", Baskerville, Georgia, Times, serif; color: #999; text-shadow: 2px 2px 2px rgba(200, 200, 200, 0.5); }
::-moz-selection{ background:#FF5E99; color:#fff; }
::selection { background:#FF5E99; color:#fff; }
details { display:block; }
a { color: rgb(36, 109, 56); text-decoration:none; }
a:hover { color: rgb(96, 73, 141) ; text-shadow: 2px 2px 2px rgba(36, 109, 56, 0.5); }
span[frown] { transform: rotate(90deg); display:inline-block; color: #bbb; }
body { text-align: center;}
h1 { font-size: 50px; text-align: center }
span[frown] { transform: rotate(90deg); display:inline-block; color: #bbb; }
body { font: 20px Constantia, 'Hoefler Text', "Adobe Caslon Pro", Baskerville, Georgia, Times, serif; color: #999; text-shadow: 2px 2px 2px rgba(200, 200, 200, 0.5); }
::-moz-selection{ background:#FF5E99; color:#fff; }
::selection { background:#FF5E99; color:#fff; }
article {display:block; text-align: left; width: 500px; margin: 0 auto; }
a { color: rgb(36, 109, 56); text-decoration:none; }
a:hover { color: rgb(96, 73, 141) ; text-shadow: 2px 2px 2px rgba(36, 109, 56, 0.5); }
</style>
<details>
<summary><h1>Not found</h1></summary>
<p><span frown>:(</span></p>
</details>
<article>
<h1>Not found <span frown>:(</span></h1>
<div>
<p>Sorry, but the page you were trying to view does not exist.</p>
<p>It looks like this was the result of either:</p>
<ul>
<li>a mistyped address</li>
<li>an out-of-date link</li>
</ul>
</div>
<script>
var GOOG_FIXURL_LANG = (navigator.language || '').slice(0,2),
GOOG_FIXURL_SITE = location.host;
</script>
<script src="http://linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js"></script>
</article>

View File

@@ -1,129 +0,0 @@
# HTML5 Boilerplate [http://html5boilerplate.com](http://html5boilerplate.com)
## Changelog:
### v.0.9.5 : October 25th, 2010
Major changes:
<ul>
<li>Removed <code>-webkit-font-smoothing: antialiased;</code> it makes monospace too thin.</li>
<li>IE conditional classes have moved from the <code>&lt;body&gt;</code> tag to the <code>&lt;html&gt;</code> tag ( #44 ).</li>
<li>Dropped <code>text-rendering: <a href="http://www.aestheticallyloyal.com/public/optimize-legibility/">optimizeLegibility</a></code> as it breaks small-caps, looks odd on Linux machines, and goes invisible on WebOS.</li>
<li>Added a IE6 call for the minified <code>dd_belatedpng</code>.</li>
<li>Revised viewport declaration to allow user scaling and clear Webkit console errors ( #37 ).</li>
<li>Updated Modernizr to 1.6 </li>
<li>Added <code>web.config</code> file for Microsoft IIS</li>
<li>Beta release of the <a href="http://github.com/paulirish/html5-boilerplate/wiki/Build-script ">Build Script</a> (this is HUGE)</li>
<li>New project scaffolding <a href="http://github.com/paulirish/html5-boilerplate/wiki/makep.sh">bash script</a>.</li>
<li><a href="http://github.com/paulirish/html5-boilerplate/blob/master/README.markdown">.... and over 100 other fixes and improvements.</a></li>
</ul>
#### General
* Updated Modernizr to 1.6 (smaller and faster)
* Added web.config file for Microsoft IIS. Now forcing latest IE version and ChromeFrame, if installed.
* Added favicon and default icon for iOS.
* Updated crossdomain.xml wording for better security guidelines ( #124 ).
* Expires value for nginx.conf corrected.
* License clarified.
#### style.css
* Removed -webkit-font-smoothing: antialiased; as it made monospace too thin.
* Updated fonts normalization to YUI 3.2.0 PR1.
* Table Header set explicitly for IE6 and table row now has page-break: avoid in print CSS.
* text-shadow:none !important set for all text in print css.
* Removed scrollbar from textareas in IE.
* Fixed textarea stylings and form field treatment for validity. Added default background-color.
* New robust clearfix solution without IE 5.5 hack ( #45 #126 ).
* Margins for form-elements explicitly set to 0 as webkit adds 2px space around form elements' chrome.
* Dropped text-rendering: optimizeLegibility as it breaks small-caps and looks odd on Linux machines.
* Lists now have a left margin of 1.8em. Default list-style-type for ordered list is decimal.
* Image Replacement now works with right-to-left text ( #68 ).
* Removed "Star Hack" for checkboxes in favor of .ie7 selector.
#### index.html
* IE conditional classes have moved from the <body> tag to the <html> tag ( #44 ).
* Added a IE6 call for the minified dd_belatedpng.
* Google Analytics script will now work with SSL in IE6.
* Added protocol independent absolute path for cdn jquery, with improved fallback-to-local code to protect against edge case IE bug.
* Commented out handheld CSS ( #73 ).
* Mobile viewport and textsize styles adjusted per group feedback ( #37 ).
#### .htaccess
* More files are served via gzip like .htc ( #55 ).
* Added Expires header for content types image/gif and video/webm.
* Fixed favicon display in IE6 ( #113 ).
* Corrected mimetypes for fonts.
* Removed caching for files of type json/xml.
* Better use of ifmodule for more stability in different Apache environments.
[View full diff and commit history](http://github.com/paulirish/html5-boilerplate/compare/v0.9.1)
#### Contributors
Shi Chuan, Rob Larsen, Ivan Nikolić, Mikko Tikkanen, Paul Neave, Weston Ruter, Jeffrey Barke, Robert Meissner, SirFunk, Philip von Bargen, Kroc Camen, Andreas Madsen, Marco d'Itri, Adeelejaz, James Rosen, Dave DeSandro, Ken Newman, Swaroop C H, Yann Mainier, Joe Sak, Irakli, Rob Flaherty, Jeff Starr, Mike Lamb, Holek, Aaron Peters, Kaelig, Meander, Charlie Ussery, Ciney, Région Wallonne and Paul Hayes.
### v.0.9.1 : August 13th, 2010
* HTML5 Boilerplate is now in the Public Domain
* Nginx configuration added
* Font stacks (sans-serif and monospace) simplified
* Very accessible a:focus styles.
* Corrected IE=edge,chromeframe enabling (As a result, the base HTML [does not validate](http://bit.ly/cGSSgr))
* ServerSideIncludes disabled by default.
* Apache config bugfixes
* Conditional body tag class combined
* dd_belatedPNG updated to 0.0.8. Redundant BackgroundImageCache fix removed.
[View full diff and commit history](http://github.com/paulirish/html5-boilerplate/compare/v0.9...v0.9.1)
##### Thanks:
voodootikigod, garowetz, fearphage, christopherjacob, mathias byenens, daniel harttman, rse, chris dary, erik dahlstrom, timwillison, ken nordahl, riddle, elcuervo, andreas kuckartz, 3rdEden, riley willis, majic3
### v0.9 : August 10th, 2010 - Initial release
## License:
Major components:
* Modernizr: MIT/BSD license
* jQuery: MIT/GPL license
* DD_belatedPNG: MIT license
* YUI Profiling: BSD license
* HTML5Doctor CSS reset: Creative Commons 3.0 BY
* CSS Reset Reloaded: Public Domain
Everything else:
* [The Unlicense](http://unlicense.org) (aka: public domain)
## Summary:
This is a set of files that a front-end developer can use to get started on a website, with following included:
1. Cross-browser compatible (IE6, yeah we got that.)
2. HTML5 ready. Use the new tags with certainty.
3. Optimal caching and compression rules for grade-A performance
4. Best practice site configuration defaults
5. Think there's too much? The HTML5 Boilerplate is delete-key friendly. :)
6. Mobile browser optimizations
7. Progressive enhancement graceful degredation ........ yeah yeah we got that
8. IE specific classes for maximum cross-browser control
9. Want to write unit tests but lazy? A full, hooked up test suite is waiting for you.
10. Javascript profiling.. in IE6 and IE7? Sure, no problem.
11. Console.log nerfing so you won't break anyone by mistake.
12. Never go wrong with your doctype or markup!
13. An optimal print stylesheet, performance optimized
14. iOS, Android, Opera Mobile-adaptable markup and CSS skeleton.
15. IE6 pngfix baked in.
16. jQuery, waiting for you
## Releases
There are two releases: a documented release, which is exactly what you see here, and a "stripped" release, with most of the descriptive comments stripped out.
Watch the [current tickets](http://github.com/paulirish/html5-boilerplate/issues) to view the areas of active development.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 747 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 640 B

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,3 @@
# build.properties file defines overrides for default.properties
# Explaination: This file should be created by each user as and when he or she needs to override particular values.
# Explanation: This file should be created by each user as and when he or she needs to override particular values.
# Consequently, it should not be placed under version control.

View File

@@ -0,0 +1,80 @@
#
# Default Build Settings
# you can override these settings on a project basis in a project.properties file
# so probably best not to touch these as they could be overwritten in later versions!
#
#
# Directory Paths
#
dir.source = .
dir.publish = publish
dir.build = build
dir.build.tools = ${dir.build}/tools
dir.test = test
dir.demo = demo
dir.js = js
dir.js.main = ${dir.js}
# scripts in the lib direcotry will only be minified, not concatenated together
dir.js.libs = ${dir.js}/libs
dir.js.mylibs = ${dir.js}/mylibs
dir.css = css
dir.images = img
#
# HTML, PHP, etc files to clean and update script/css references
#
file.pages.default.include = index.html, 404.html
# You will need to include the property file.pages.include in your project.properties file
# and add any extra pages you want to be updated by the scripts in a comma separated lis
# the server configuration you're going with. If you don't use apache,
# get a different one here: github.com/paulirish/html5-boilerplate-server-configs
file.serverconfig = .htaccess
#
# Files not to be copied over by the script to the publish directory
#
file.default.exclude = .gitignore, .project, .settings, README.markdown, README.md, ${dir.images}/*.jpg, **/.git/**, **/.svn/**, **/${dir.build}/**, **/${dir.test}/**, **/${dir.demo}/**
# Declare the file.exclude property in your project.properties file if you want to exclude files / folders you have added
# Note: you cannot decalre an empty file.exclude property
#
# Default Styleshee
#
file.default.stylesheets = style.css
#
# Script Optimisation
#
# If set, concat libraries with main scripts file, producing single script file
build.concat.scripts = true
# If set, delete minified but unconcatted files.
build.delete.unoptimized = true
#
# Image Optimisation
#
images.strip.metadata = true
# Seting this to true will strip the metadata from all jpeg files.
# YOU SHOULD ONLY DO THIS IF YOU OWN THE COPYRIGHT TO ALL THE IMAGES IN THE BUILD
# Build Info
build.version.info = buildinfo.properties
build.scripts.dir = ${dir.build}/build-scripts
# Tools
tool.yuicompressor = yuicompressor-2.4.2.jar
tool.htmlcompressor = htmlcompressor-0.9.9.jar
tool.csscompressor = css-compressor/cli.php

View File

@@ -0,0 +1,55 @@
# project.properties file defines overrides for default.properties
# Explanation: This file should be created by each user as and when he or she needs to override particular values.
# Consequently, it should not be placed under version control.
# Stylesheets
#
# Note: Stylesheets will be concatenated in the order they are listed in the file.stylesheets property (i.e. the las
# file listed will be at the end of the concatenated file), so it probably makes sense to have the main style.css file
# as the first entry
# Example:
# file.stylesheets = style.css, lightbox.css, plugin.css
#
file.stylesheets =
# Web Pages
#
# These are the pages (files) that will be served to users (.html, .php, .asp, etc). Files in this property will
# be minified / optimised and have any stylesheet or javascript references updated to the minified examples
#
# The paths need to be relative
#
# Files can be added in a comma separated form
file.pages =
# Excluded files and dirs
#
# Add any files or directories you add to the project and do not want to be copied to the publish directory as a
# comma separated lis
# These files are ignored in addition to the default ones specified in default.properties.
file.exclude =
# Specify an environment to build
#
# By Default, it builds a production environmen
# Set to dev if buidling a development environmen
# Set to test if building a test environmen
env =
# Directory Structure
#
# Override any directory paths specific to this projec
#
# dir.publish
# dir.js
# dir.js.libs
# dir.js.mylibs
# dir.css
# dir.images

View File

@@ -5,69 +5,38 @@
##first run
# $ cd html5-boilerplate
# $ sudo chmod a+x createproject.sh && ./createproject.sh
# $ cd html5-boilerplate/build
# $ chmod +x createproject.sh && ./createproject.sh
##usage
# $ cd html5-boilerplate/build
# $ ./createproject.sh
echo "To create a new html5-boilerplate project, enter a new directory name:"
# find project root (also ensure script is ran from within repo)
src=$(git rev-parse --show-toplevel) || exit 1
read name
# get a name for new project
while [[ -z $name ]]
do
echo "To create a new html5-boilerplate project, enter a new directory name:"
read name || exit
done
dst=$src/../$name
cd ..
webroot=$PWD
SRC=$webroot"/html5-boilerplate"
DST=$webroot"/../"$name
if [ -d "$DST" ]
if [[ -d $dst ]]
then
echo "$DST exists"
echo "$dst exists"
else
#create new project
mkdir $name
mkdir "$dst" || exit 1
#sucess message
echo "Created Directory: $DST"
cd $SRC
#copy to new project directory
#http://en.wikipedia.org/wiki/Cpio#Copy
#http://cybertiggyr.com/cpio-howto/
#http://www.cyberciti.biz/faq/how-do-i-use-cpio-command-under-linux/
find . -depth -print0 | cpio -0pdmv $DST
echo "Created Directory: $dst"
cd "$src"
cp -vr css/ js/ img/ *.html *.xml *.txt *.png *.ico .htaccess "$dst"
#sucess message
echo "Created Project: $DST"
# delete that temporary folder
rm -r $name
#move into new project
cd $DST
#in Bourne Again Shell, the cpio was copying
#the whole dir into the new project, along with the contents
if [ -d "$DST/html5-boilerplate" ]
then
rm -r html5-boilerplate
fi
if [ -e "$DST/createproject.sh" ]
then
rm -r createproject.sh
fi
if [ -e "$DST/.git" ]
then
rm -rf .git
fi
echo "Created Project: $dst"
fi

View File

@@ -1,52 +0,0 @@
# Build options ---------------------------------
# Customize these to fit your needs
# If set, concat libraries with main scripts file, producing single script file
build.concat.scripts = true
# If set, delete unoptimized files
build.delete.unoptimized = true
# Exclude file filter for publishing (can't be empty)
# For example: ...<add example here>...
file.exclude = nonexistentfile
# Project structure -----------------------------
# Directory names
dir.publish = publish
dir.build = build
dir.tools = ${dir.build}/tools
dir.test = test
dir.demo = demo
dir.js = js
# Main JS script folder (Will be concatenated and minified)
dir.js.main = ${dir.js}
# JS libraries folder (Will be concatenated and minified)
dir.js.mylibs = ${dir.js}/mylibs
# Folder that should be only minified, not concatenated together
dir.js.libs = ${dir.js}/libs
dir.css = css
dir.images = images
# Files
# all the html/php whatever that the build script will be mucking with.
# For example: ...<add example here>...
file.index = index.html
# Hardcore build options... --------------------
# Build Versioning
build.info = buildinfo.properties
# Tools
tool.yuicompressor = yuicompressor-2.4.2.jar

5
build/runbuildscript.bat Normal file
View File

@@ -0,0 +1,5 @@
# This is for windows users only.
# If you're on a mac or linux, just run `ant build` from this folder in Terminal
set MYDIR=%~dp0
ant build

Binary file not shown.

View File

@@ -0,0 +1,465 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
// Static dependencies, Subclasses loaded ondemand
require( dirname(__FILE__) . '/lib/Exception.php' );
require( dirname(__FILE__) . '/lib/Control.php' );
Class CSSCompression
{
/**
* CSSCompression Info
*
* @const (string) VERSION: Release version
* @const (string) DATE: Release date
*/
const VERSION = "[VERSION]";
const DATE = "[DATE]";
/**
* WARNING: This should ALWAYS BE FALSE in production
* When DEV is true, backdoor access to private methods is opened.
* Only used for unit testing and development.
*/
const DEV = true;
/**
* TOKEN is a special string that gets used as a marker within
* the compressor, and is removed before final output. Make sure
* this token is unique to your stylsheets.
*
* NOTE: This string gets used in regular expressions, and escaping
* won't help, so don't pick a complicated token.
*/
const TOKEN = "@____CSSCOMPRESSION_TOKEN____@";
/**
* The default set of options for every instance.
*/
public static $defaults = array(
// Converts long color names to short hex names
// (aliceblue -> #f0f8ff)
'color-long2hex' => true,
// Converts rgb colors to hex
// (rgb(159,80,98) -> #9F5062, rgb(100%) -> #FFFFFF)
'color-rgb2hex' => true,
// Converts long hex codes to short color names (#f5f5dc -> beige)
// Only works on latest browsers, careful when using
'color-hex2shortcolor' => false,
// Converts long hex codes to short hex codes
// (#44ff11 -> #4f1)
'color-hex2shorthex' => true,
// Converts hex codes to safe CSS Level 1 color names
// (#F00 -> red)
'color-hex2safe' => true,
// Converts font-weight names to numbers
// (bold -> 700)
'fontweight2num' => true,
// Removes zero decimals and 0 units
// (15.0px -> 15px || 0px -> 0)
'format-units' => true,
// Lowercases html tags from list
// (BODY -> body)
'lowercase-selectors' => true,
// Converts id and class attribute selectors, to their short selector counterpart
// (div[id=blah][class=moreblah] -> div#blah.moreblah)
'attr2selector' => true,
// Promotes nested id's to the front of the selector
// (body>div#elem p -> $elem p)
'strict-id' => false,
// Add space after pseudo selectors, for ie6
// (a:first-child{ -> a:first-child {)
'pseudo-space' => false,
// Compresses single defined multi-directional properties
// (margin: 15px 25px 15px 25px -> margin:15px 25px)
'directional-compress' => true,
// Combines multiply defined selectors and details
// (p{color:blue;} p{font-size:12pt} -> p{color:blue;font-size:12pt;})
// (p{color:blue;} a{color:blue;} -> p,a{color:blue;})
'organize' => true,
// Combines color/style/width properties
// (border-style:dashed;border-color:black;border-width:4px; -> border:4px dashed black)
'csw-combine' => true,
// Combines cue/pause properties
// (cue-before: url(before.au); cue-after: url(after.au) -> cue:url(before.au) url(after.au))
'auralcp-combine' => true,
// Combines margin/padding directionals
// (margin-top:10px;margin-right:5px;margin-bottom:4px;margin-left:1px; -> margin:10px 5px 4px 1px;)
'mp-combine' => true,
// Combines border directionals
// (border-top|right|bottom|left:1px solid black -> border:1px solid black)
'border-combine' => true,
// Combines font properties
// (font-size:12pt; font-family: arial; -> font:12pt arial)
'font-combine' => true,
// Combines background properties
// (background-color: black; background-image: url(bgimg.jpeg); -> background:black url(bgimg.jpeg))
'background-combine' => true,
// Combines list-style properties
// (list-style-type: round; list-style-position: outside -> list-style:round outside)
'list-combine' => true,
// Combines border-radius properties
// {
// border-top-left-radius: 10px;
// border-top-right-radius: 10px;
// border-bottom-right-radius: 10px;
// border-bottom-left-radius: 10px;
// }
// -> { border-radius: 10px; }
'border-radius-combine' => true,
// Removes the last semicolon of a property set
// ({margin: 2px; color: blue;} -> {margin: 2px; color: blue})
'unnecessary-semicolons' => true,
// Removes multiple declarations within the same rule set
'rm-multi-define' => true,
// Adds all unknown blocks to the top of the output in a comment strip
// Purely for bug reporting, but also useful to know what isn't being handled
'add-unknown' => true,
// Readibility of Compressed Output, Defaults to none
'readability' => 0,
);
/**
* Modes are predefined sets of configuration for referencing. When creating a mode, all options are set to true,
* and the mode array defines which options are to be false
*
* @mode safe: Safe mode does zero combinations or organizing. It's the best mode if you use a lot of hacks
* @mode sane: Sane mode does most combinations(multiple long hand notations to single shorthand),
* --- but still keeps most declarations in their place
* @mode small: Small mode reorganizes the whole sheet, combines as much as it can, and will break most comment hacks
* @mode full: Full mode does everything small does, but also converts hex codes to their short color name alternatives
*/
private static $modes = array(
'safe' => array(
'color-hex2shortcolor' => false,
'attr2selector' => false,
'strict-id' => false,
'organize' => false,
'csw-combine' => false,
'auralcp-combine' => false,
'mp-combine' => false,
'border-combine' => false,
'font-combine' => false,
'background-combine' => false,
'list-combine' => false,
'border-radius-combine' => false,
'rm-multi-define' => false,
),
'sane' => array(
'color-hex2shortcolor' => false,
'strict-id' => false,
'organize' => false,
'font-combine' => false,
'background-combine' => false,
'list-combine' => false,
'rm-multi-define' => false,
),
'small' => array(
'color-hex2shortcolor' => false,
'pseudo-space' => false,
),
'full' => array(
'pseudo-space' => false,
),
);
/**
* Readability Constants
*
* @param (int) READ_MAX: Maximum readability of output
* @param (int) READ_MED: Medium readability of output
* @param (int) READ_MIN: Minimal readability of output
* @param (int) READ_NONE: No readability of output (full compression into single line)
*/
const READ_MAX = 3;
const READ_MED = 2;
const READ_MIN = 1;
const READ_NONE = 0;
/**
* Static Helpers
*
* @instance express: Use a separate instance from singleton access
* @instance instance: Saved instance of CSSCompression
* @param (array) instances: Array of stored instances
* @param (array) rjson: Comment removal before json decoding
*/
private static $express;
private static $instance;
private static $instances = array();
private static $rjson = array(
'patterns' => array(
"/^(.*?){/s",
"/(\t|\s)+\/\/.*/",
),
'replacements' => array(
'{',
'',
),
);
/**
* Controller Instance
*/
private $Control;
/**
* Builds the subclasses, runs the compression if css passed, and merges options
*
* @param (string) css: CSS to compress on initialization if needed
* @param (array) options: Array of preferences to override the defaults
*/
public function __construct( $css = NULL, $options = NULL ) {
$this->Control = new CSSCompression_Control( $this );
// Autorun against css passed
if ( $css ) {
// Allow passing options/mode only
if ( is_array( $css ) || array_key_exists( $css, self::$modes ) ) {
$this->Control->Option->merge( $css );
}
else {
$this->Control->compress( $css, $options );
}
}
// Merge passed options
else if ( $options ) {
$this->Control->Option->merge( $options );
}
}
/**
* (Proxy function) Control access to properties
*
* - Getting stats/_mode/css returns the current value of that property
* - Getting options will return the current full options array
* - Getting anything else returns that current value in the options array or NULL
*
* @param (string) name: Name of property that you want to access
*/
public function __get( $name ) {
return $this->Control->get( $name );
}
/**
* (Proxy function) The setter method only allows
* access to setting values in the options array
*
* @param (string) name: Key name of the option you want to set
* @param (mixed) value: Value of the option you want to set
*/
public function __set( $name, $value ) {
return $this->Control->set( $name, $value );
}
/**
* (Proxy function) Merges a predefined set options
*
* @param (string) mode: Name of mode to use.
*/
public function mode( $mode = NULL ) {
return $this->Control->Option->merge( $mode );
}
/**
* Creates a new mode, or overwrites existing mode
*
* @param (mixed) mode: Name of the mode, or array of modes
* @param (array) config: Configuration of the mode
*/
public static function modes( $mode = NULL, $config = NULL ) {
if ( $mode === NULL ) {
return self::$modes;
}
else if ( is_array( $mode ) ) {
return array_merge( self::$modes, $mode );
}
else if ( $config === NULL ) {
return isset( self::$modes[ $mode ] ) ? self::$modes[ $mode ] : NULL;
}
else {
return self::$modes[ $mode ] = $config;
}
}
/**
* (Proxy function) Maintainable access to the options array
*
* - Passing no arguments returns the entire options array
* - Passing a single name argument returns the value for the option
* - Passing an array will merge the options with the array passed, for object like extension
* - Passing both a name and value, sets the value to the name key, and returns the value
*
* @param (mixed) name: The key name of the option
* @param (mixed) value: Value to set the option
*/
public function option( $name = NULL, $value = NULL ) {
return $this->Control->Option->option( $name, $value );
}
/**
* (Proxy function) Run compression on the sheet passed.
*
* @param (string) css: Stylesheet to be compressed
* @param (mixed) options: Array of options or mode to use.
*/
public function compress( $css = NULL, $options = NULL ) {
return $this->Control->compress( $css, $options );
}
/**
* Static access for direct compression
*
* @param (string) css: Stylesheet to be compressed
* @param (mixed) options: Array of options or mode to use.
*/
public static function express( $css = NULL, $options = NULL ) {
if ( ! self::$express ) {
self::$express = new CSSCompression();
}
self::$express->reset();
return self::$express->compress( $css, $options );
}
/**
* (Proxy Function) Cleans out compressor and it's subclasses to defaults
*
* @params none
*/
public function reset(){
return $this->Control->reset();
}
/**
* (Proxy Function) Cleans out class variables for next run
*
* @params none
*/
public function flush(){
return $this->Control->flush();
}
/**
* The Singleton access method (for those that want it)
*
* @param (string) name: Name of the stored instance
*/
public static function getInstance( $name = NULL ) {
if ( $name !== NULL ) {
if ( ! isset( self::$instances[ $name ] ) ) {
self::$instances[ $name ] = new self;
}
return self::$instances[ $name ];
}
else if ( ! self::$instance ) {
self::$instance = new self;
}
return self::$instance;
}
/**
* Reads JOSN based files, strips comments and converts to array
*
* @param (string) file: Filename
*/
public static function getJSON( $file ) {
// Assume helper file if full path not given
$file = $file[ 0 ] == '/' ? $file : dirname(__FILE__) . '/helpers/' . $file;
// Strip comments
$json = preg_replace( self::$rjson['patterns'], self::$rjson['replacements'], file_get_contents( $file ) );
// Decode json
$json = json_decode( $json, true );
// Check for errors
if ( $json === NULL ) {
$e = '';
// JSON Errors, taken directly from http://php.net/manual/en/function.json-last-error.php
switch( json_last_error() ) {
case JSON_ERROR_NONE:
$e = 'No error has occurred';
break;
case JSON_ERROR_DEPTH:
$e = 'The maximum stack depth has been exceeded';
break;
case JSON_ERROR_CTRL_CHAR:
$e = 'Control character error, possibly incorrectly encoded';
break;
case JSON_ERROR_STATE_MISMATCH:
$e = 'Invalid or malformed JSON';
break;
case JSON_ERROR_SYNTAX:
$e = 'Syntax error';
break;
case JSON_ERROR_UTF8:
$e = 'Malformed UTF-8 characters, possibly incorrectly encoded';
break;
default:
$e = 'Unknown JSON Error';
break;
}
throw new CSSCompression_Exception( "JSON Error in $file: $e" );
}
// Good to go
return $json;
}
/**
* Backdoor access to subclasses
* ONLY FOR DEVELOPMENT/TESTING.
*
* @param (string) class: Name of the focus class
* @param (string) method: Method function to call
* @param (array) args: Array of arguments to pass in
*/
public function access( $class = NULL, $method = NULL, $args = NULL ) {
if ( ! self::DEV ) {
throw new CSSCompression_Exception( "CSSCompression is not in development mode." );
}
else if ( $class === NULL || $method === NULL || $args === NULL ) {
throw new CSSCompression_Exception( "Invalid Access Call." );
}
else if ( ! is_array( $args ) ) {
throw new CSSCompression_Exception( "Expecting array of arguments." );
}
return $this->Control->access( $class, $method, $args );
}
};
?>

View File

@@ -0,0 +1,22 @@
#
# CSS Compression [VERSION] Change Log
# [DATE]
# Corey Hart @ http://www.codenothing.com
#
# Compressor Additions
- Configuration Modes
- pseduo-space, add space between pseduo selectors and comma/brace for ie6
- removing leading 0 of a decimal, 0.633px -> .633px
- handling all At Rules (charsets,media,imports,font-family,etc..)
- handling ms filter paths
- More css hacks support, including box-modal hack
- attr2selector, Convert id=blah and class=blah attributes to their selector counterparts
- strict-id, removes all selectors up to the last id
- add-unknown, adds unknown blocks to top of output in a comment
# Codebase Changes
- Converted to subclass architecture, more modular.
- Using JSON based sandbox specs for focused unit tests.
- Helper conversion definitions(long2hex, hex2short) are now in JSON based files.
- Added benchmark/regression testing

View File

@@ -0,0 +1,228 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
require( dirname(__FILE__) . '/CSSCompression.php' );
Class CSSCompression_Cli
{
/**
* Cli Patterns
*
* @param (CSSCompression instance) instance: CSSCompression instance
* @param (array) args: Array of command line arguments
* @param (array) options: Array of options read from cli arguments
* @param (boolean) imports: Read import paths from the filesystem, and inject them into the script
* @param (string) mode: Compression mode
* @param (string) cwd: Current working directory
* @param (string) content: CSS Sheets read
* @param (regex) rcss: Matches css file name extension
* @param (regex) rprefix: Matches absolute paths
* @param (regex) rmarker: Marking points in css files when parsing for imports
* @param (regex) rquote: Unescaped quote
* @param (regex) rsinglequote: Unescaped single quote
* @param (regex) rsemicolon: Unescaped semicolon
* @param (regex) rimporturl: Import statement in a url() wrapper
* @param (regex) rimportstr: Import statement in a string wrapper
* @param (regex) rabsolutepath: Absolute path checker for import urls
* @param (regex) rfsabsolutepath: Matches absolute paths for the file system
*/
private $instance;
private $args = array();
private $options = array();
private $files = array();
private $imports = true;
private $mode = 'safe';
private $cwd = '';
private $content = '';
private $rcss = "/\.css$/";
private $rchopfile= "/\/[^\/]*$/";
private $rmarker = "/(\/\*|\"|'|@import)/";
private $rquote = "/(?<!\\\)\"/";
private $rsinglequote = "/(?<!\\\)'/";
private $rsemicolon = "/(?<!\\\);/";
private $rimporturl = "/^@import url\(['\"]?(.*?)['\"]?\)/";
private $rimportstr = "/^@import ['\"](.*?)['\"]/";
private $rabsolutepath = "/^(https?:\/\/|\/)/";
private $rfsabsolutepath = "/^(\/|\~\/|\\\|[a-z]:(\\\|\/)?)/i";
/**
* Run the compression across files passed to cli
*
* @param (array) args: Array of argument passed over the command line
*/
public function __construct( $args = array() ) {
// Render arguments
$this->cwd = getcwd() . DIRECTORY_SEPARATOR;
$this->args = $args;
$this->read();
// Run the files through the css compressor
$this->render();
}
/**
* Reads the cli arguments and puts them in their place
*
* @params none
*/
private function read(){
while ( count( $this->args ) ) {
$arg = array_shift( $this->args );
// Adding contents of css files
if ( preg_match( $this->rcss, $arg ) ) {
// Handle absolute path prefixing
if ( ! preg_match( $this->rfsabsolutepath, $arg ) && strpos( $arg, $this->cwd ) === false) {
$path = $this->cwd . $arg;
}
else {
$path = $arg;
}
$this->content .= $this->imports( $path );
}
// Longhand options
else if ( substr( $arg, 0, 2 ) == '--' ) {
$parts = explode( '=', $arg, 2 );
$name = substr( $parts[ 0 ], 2 );
$value = isset( $parts[ 1 ] ) ? $parts[ 1 ] : true;
if ( $name == 'mode' ) {
$this->mode = $value;
}
else if ( $name == 'imports' ) {
$this->imports = true;
}
else {
// Argument value is passed as string,
// convert to boolean as needed
if ( $value == 'false' ) {
$value = false;
}
else if ( $value == 'true' ) {
$value = true;
}
else {
$value = intval( $value );
}
$this->options[ $name ] = $value;
}
}
// Shorthand options
else if ( substr( $arg, 0, 1 ) == '-' && strlen( $arg ) == 2 ) {
$char = substr( $arg, 1, 1 );
if ( $char == 'i' ) {
$this->imports = true;
}
}
}
}
/**
* Scans the css file for import defns
*
* @param (path) file: Path to the stylesheet passed as an argument
*/
private function imports( $file ) {
// Set the content and the directory of the stylesheet
$content = file_get_contents( $file );
$cwd = preg_replace( $this->rchopfile, '/', $file );
// Block import fixing if not set
if ( $this->imports === false ) {
return $content;
}
$pos = 0;
while ( preg_match( $this->rmarker, $content, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$marker = $match[ 1 ][ 0 ];
if ( $marker == '/*' ) {
if ( ( $pos = strpos( $content, '*/', $match[ 1 ][ 1 ] ) ) === false ) {
break;
}
}
else if ( $marker == '"' ) {
if ( preg_match( $this->rquote, $content, $m, PREG_OFFSET_CAPTURE, $match[ 1 ][ 1 ] + 1 ) ) {
$pos = $m[ 0 ][ 1 ] + 2;
}
else {
break;
}
}
else if ( $marker == "'" ) {
if ( preg_match( $this->rsinglequote, $content, $m, PREG_OFFSET_CAPTURE, $match[ 1 ][ 1 ] + 1 ) ) {
$pos = $m[ 0 ][ 1 ] + 2;
}
else {
break;
}
}
else if ( $marker == '@import' ) {
list ( $content, $pos ) = $this->inject( $content, $cwd, $match[ 1 ][ 1 ] );
}
else {
throw new CSSCompression_Exception( 'Unknown Import Error' );
}
}
return $content;
}
/**
* Replaces the import declaration with it's contents
*
* @param (string) content: Contents of the stylesheet
* @param (path) cwd: Directory of the current stylesheet
* @param (int) pos: Position of the import declaration
*/
private function inject( $content, $cwd, $pos ) {
if ( ! preg_match( $this->rsemicolon, $content, $m, PREG_OFFSET_CAPTURE, $pos ) ) {
throw new CSSCompression_Exception( "@import stmt at character position $pos, has no line-ending semicolon." );
}
$import = substr( $content, $pos, $m[ 0 ][ 1 ] + 1 - $pos );
// Check for valid import stmt, and replace into it the imports contents
if ( ( preg_match( $this->rimporturl, $import, $m ) || preg_match( $this->rimportstr, $import, $m ) ) &&
! preg_match( $this->rabsolutepath, $m[ 1 ] ) ) {
if ( ! file_exists( $cwd . $m[ 1 ] ) ) {
throw new CSSCompression_Exception( "Import Path '" . $cwd . $m[ 1 ] . "' not found." );
}
$content = substr_replace( $content, file_get_contents( $cwd . $m[ 1 ] ), $pos, strlen( $import ) );
}
else {
$pos += strlen( $import );
}
return array( $content, $pos );
}
/**
* Outputs the compression of the content read
*
* @params none
*/
private function render(){
$this->instance = new CSSCompression();
if ( $this->mode ) {
$this->instance->mode( $this->mode );
}
if ( $this->options ) {
$this->instance->option( $this->options );
}
echo $this->instance->compress( $this->content );
}
};
// Auto-initialize the cli script
new CSSCompression_Cli( $_SERVER['argv'] );
?>

View File

@@ -0,0 +1,39 @@
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
{
"#f0ffff":"azure",
"#f5f5dc":"beige",
"#ffe4c4":"bisque",
"#a52a2a":"brown",
"#ff7f50":"coral",
"#ffd700":"gold",
"#808080":"gray",
"#008000":"green",
"#4b0082":"indigo",
"#fffff0":"ivory",
"#f0e68c":"khaki",
"#faf0e6":"linen",
"#800000":"maroon",
"#000080":"navy",
"#808000":"olive",
"#ffa500":"orange",
"#da70d6":"orchid",
"#cd853f":"peru",
"#ffc0cb":"pink",
"#dda0dd":"plum",
"#800080":"purple",
"#ff0000":"red",
"#fa8072":"salmon",
"#a0522d":"sienna",
"#c0c0c0":"silver",
"#fffafa":"snow",
"#d2b48c":"tan",
"#008080":"teal",
"#ff6347":"tomato",
"#ee82ee":"violet",
"#f5deb3":"wheat",
"#f00":"red"
}

View File

@@ -0,0 +1,16 @@
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
{
"#808080":"gray",
"#008000":"green",
"#800000":"maroon",
"#000080":"navy",
"#808000":"olive",
"#ff0000":"red",
"#c0c0c0":"silver",
"#008080":"teal",
"#f00":"red"
}

View File

@@ -0,0 +1,127 @@
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
{
"aliceblue":"#f0f8ff",
"antiquewhite":"#faebd7",
"aquamarine":"#7fffd4",
"bisque":"#ffe4c4",
"black":"#000000",
"blanchedalmond":"#ffebcd",
"blueviolet":"#8a2be2",
"burlywood":"#deb887",
"cadetblue":"#5f9ea0",
"chartreuse":"#7fff00",
"chocolate":"#d2691e",
"coral":"#ff7f50",
"cornflowerblue":"#6495ed",
"cornsilk":"#fff8dc",
"crimson":"#dc143c",
"cyan":"#00ffff",
"darkblue":"#00008b",
"darkcyan":"#008b8b",
"darkgoldenrod":"#b8860b",
"darkgray":"#a9a9a9",
"darkgreen":"#006400",
"darkkhaki":"#bdb76b",
"darkmagenta":"#8b008b",
"darkolivegreen":"#556b2f",
"darkorange":"#ff8c00",
"darkorchid":"#9932cc",
"darkred":"#8b0000",
"darksalmon":"#e9967a",
"darkseagreen":"#8fbc8f",
"darkslateblue":"#483d8b",
"darkslategray":"#2f4f4f",
"darkturquoise":"#00ced1",
"darkviolet":"#9400d3",
"deeppink":"#ff1493",
"deepskyblue":"#00bfff",
"dimgray":"#696969",
"dodgerblue":"#1e90ff",
"firebrick":"#b22222",
"floralwhite":"#fffaf0",
"forestgreen":"#228b22",
"fuchsia":"#ff00ff",
"gainsboro":"#dcdcdc",
"ghostwhite":"#f8f8ff",
"goldenrod":"#daa520",
"green":"#008800",
"greenyellow":"#adff2f",
"honeydew":"#f0fff0",
"hotpink":"#ff69b4",
"indianred ":"#cd5c5c",
"indigo ":"#4b0082",
"lavender":"#e6e6fa",
"lavenderblush":"#fff0f5",
"lawngreen":"#7cfc00",
"lemonchiffon":"#fffacd",
"lightblue":"#add8e6",
"lightcoral":"#f08080",
"lightcyan":"#e0ffff",
"lightgoldenrodyellow":"#fafad2",
"lightgrey":"#d3d3d3",
"lightgreen":"#90ee90",
"lightpink":"#ffb6c1",
"lightsalmon":"#ffa07a",
"lightseagreen":"#20b2aa",
"lightskyblue":"#87cefa",
"lightslategray":"#778899",
"lightsteelblue":"#b0c4de",
"lightyellow":"#ffffe0",
"lime":"#00ff00",
"limegreen":"#32cd32",
"magenta":"#ff00ff",
"maroon":"#800000",
"mediumaquamarine":"#66cdaa",
"mediumblue":"#0000cd",
"mediumorchid":"#ba55d3",
"mediumpurple":"#9370d8",
"mediumseagreen":"#3cb371",
"mediumslateblue":"#7b68ee",
"mediumspringgreen":"#00fa9a",
"mediumturquoise":"#48d1cc",
"mediumvioletred":"#c71585",
"midnightblue":"#191970",
"mintcream":"#f5fffa",
"mistyrose":"#ffe4e1",
"moccasin":"#ffe4b5",
"navajowhite":"#ffdead",
"oldlace":"#fdf5e6",
"olivedrab":"#6b8e23",
"orange":"#ffa500",
"orangered":"#ff4500",
"orchid":"#da70d6",
"palegoldenrod":"#eee8aa",
"palegreen":"#98fb98",
"paleturquoise":"#afeeee",
"palevioletred":"#d87093",
"papayawhip":"#ffefd5",
"peachpuff":"#ffdab9",
"powderblue":"#b0e0e6",
"purple":"#800080",
"rosybrown":"#bc8f8f",
"royalblue":"#4169e1",
"saddlebrown":"#8b4513",
"salmon":"#fa8072",
"sandybrown":"#f4a460",
"seagreen":"#2e8b57",
"seashell":"#fff5ee",
"sienna":"#a0522d",
"silver":"#c0c0c0",
"skyblue":"#87ceeb",
"slateblue":"#6a5acd",
"slategray":"#708090",
"springgreen":"#00ff7f",
"steelblue":"#4682b4",
"thistle":"#d8bfd8",
"tomato":"#ff6347",
"turquoise":"#40e0d0",
"violet":"#ee82ee",
"white":"#ffffff",
"whitesmoke":"#f5f5f5",
"yellow":"#ffff00",
"yellowgreen":"#9acd32"
}

View File

@@ -0,0 +1,218 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Cleanup
{
/**
* Cleanup patterns
*
* @class Control: Compression Controller
* @param (string) token: Copy of the injection token
* @param (regex) rtoken: Token regex built upon instantiation
* @param (array) options: Reference to options
* @param (regex) rsemi: Checks for last semit colon in details
* @param (regex) rsemicolon: Checks for semicolon without an escape '\' character before it
* @param (regex) rspace: Checks for space without an escape '\' character before it
* @param (regex) rcolon: Checks for colon without an escape '\' character before it
* @param (regex) rquote: Checks for quote (') without an escape '\' character before it
* @param (array) rescape: Array of patterns for groupings that should be escaped
* @param (array) escaped: Contains patterns and replacements for espaced characters
*/
private $Control;
private $token = '';
private $rtoken = '';
private $options = array();
private $rsemi = "/;$/";
private $rsemicolon = "/(?<!\\\);/";
private $rspace = "/(?<!\\\)\s/";
private $rcolon = "/(?<!\\\):/";
private $rquote = "/(?<!\\\)'/";
private $rescape = array(
"/((?<!\\\)\")(.*?)((?<!\\\)\")/",
"/((?<!\\\)')(.*?)((?<!\\\)')/",
"/(url\()(.*?)(\))/",
);
private $escaped = array(
'search' => array(
"\\:",
"\\;",
"\\}",
"\\{",
"\\@",
"\\!",
"\\,",
"\\>",
"\\+",
"\\~",
"\\/",
"\\*",
"\\.",
"\\=",
"\\#",
"\\r",
"\\n",
"\\t",
"\\ ",
),
'replace' => array(
":",
";",
"}",
"{",
"@",
"!",
",",
">",
"+",
"~",
"/",
"*",
".",
"=",
"#",
"\r",
"\n",
"\t",
" ",
),
);
/**
* Build the token regex based on defined token
*
* @param (class) control: CSSCompression Controller
*/
public function __construct( CSSCompression_Control $control ) {
$this->Control = $control;
$this->token = CSSCompression::TOKEN;
$this->options = &$control->Option->options;
// Have to build the token regexs after initialization
$this->rtoken = "/($this->token)(.*?)($this->token)/";
array_push( $this->rescape, $this->rtoken );
}
/**
* Central cleanup process, removes all injections
*
* @param (array) selectors: Array of selectors
* @param (array) details: Array of details
*/
public function cleanup( &$selectors, &$details ) {
foreach ( $details as $i => &$value ) {
// Auto skip sections
if ( isset( $selectors[ $i ] ) && strpos( $selectors[ $i ], $this->token ) === 0 ) {
continue;
}
// Removing dupes
if ( $this->options['rm-multi-define'] ) {
$value = $this->removeMultipleDefinitions( $value );
}
$value = $this->removeUnnecessarySemicolon( $value );
}
return array( $selectors, $details );
}
/**
* Removes '\' from possible splitter characters in URLs
*
* @param (string) css: Full css sheet
*/
public function removeInjections( $css ) {
// Remove escaped characters
foreach ( $this->rescape as $regex ) {
$pos = 0;
while ( preg_match( $regex, $css, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$value = $match[ 1 ][ 0 ]
. str_replace( $this->escaped['search'], $this->escaped['replace'], $match[ 2 ][ 0 ] )
. $match[ 3 ][ 0 ];
$css = substr_replace( $css, $value, $match[ 0 ][ 1 ], strlen( $match[ 0 ][ 0 ] ) );
$pos = $match[ 0 ][ 1 ] + strlen( $value ) + 1;
}
}
// Remove token injections
$pos = 0;
while ( preg_match( $this->rtoken, $css, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$value = $match[ 2 ][ 0 ];
if ( preg_match( $this->rspace, $value ) ) {
$quote = preg_match( $this->rquote, $value ) ? "\"" : "'";
$value = "$quote$value$quote";
$css = substr_replace( $css, $value, $match[ 0 ][ 1 ], strlen( $match[ 0 ][ 0 ] ) );
$pos = $match[ 0 ][ 1 ] + strlen( $value ) + 1;
}
else {
$css = substr_replace( $css, $value, $match[ 0 ][ 1 ], strlen( $match[ 0 ][ 0 ] ) );
$pos = $match[ 0 ][ 1 ] + strlen( $value ) + 1;
}
}
return $css;
}
/**
* Removes multiple definitions that were created during compression
*
* @param (string) val: CSS Selector Properties
*/
private function removeMultipleDefinitions( $val = '' ) {
$storage = array();
$arr = preg_split( $this->rsemicolon, $val );
foreach ( $arr as $x ) {
if ( $x ) {
list( $a, $b ) = preg_split( $this->rcolon, $x, 2 );
$storage[ $a ] = $b;
}
}
if ( $storage ) {
$val = '';
foreach ( $storage as $x => $y ) {
$val .= "$x:$y;";
}
}
// Return converted val
return $val;
}
/**
* Removes last semicolons on the final property of a set
*
* @param (string) value: rule set
*/
private function removeUnnecessarySemicolon( $value ) {
return preg_replace( $this->rsemi, '', $value );
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
if ( $method == 'cleanup' ) {
return $this->cleanup( $args[ 0 ], $args[ 1 ] );
}
else {
return call_user_func_array( array( $this, $method ), $args );
}
}
else {
throw new CSSCompression_Exception( "Unknown method in Cleanup Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,199 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Color
{
/**
* Color Patterns
*
* @class Control: Compression Controller
* @param (array) options: Reference to options array
* @param (regex) rrgb: Checks for rgb notation
* @param (regex) rhex: Checks for hex code
* @param (regex) rfullhex: Checks for full 6 character hex code
* @static (array) color2hex: Long color name to hex code conversions
* @static (array) hex2short: Hex code to short color name conversions
* @static (array) hex2short_safe: CSS Level 1 safe color names that are shorter than hex codes
* @static (array) files: List of static helpers with their class vars
*/
private $Control;
private $options = array();
private $rrgb = "/^rgb\((\d{1,3}\%?(,\d{1,3}\%?,\d{1,3}\%?)?)\)$/i";
private $rhex = "/^#([0-9a-f]{3}|[0-9a-f]{6})$/i";
private $rfullhex = "/^#([0-9a-f]{6})$/i";
private static $color2hex = array();
private static $hex2short = array();
private static $hex2short_safe = array();
private static $files = array(
'color2hex' => 'long2hex-colors.json',
'hex2short' => 'hex2short-colors.json',
'hex2short_safe' => 'hex2short-safe.json',
);
/**
* Stash a reference to the controller on each instantiation
* and install conversion helpers
*
* @param (class) control: CSSCompression Controller
*/
public function __construct( CSSCompression_Control $control ) {
$this->Control = $control;
$this->options = &$control->Option->options;
if ( ! self::$color2hex ) {
foreach ( self::$files as $v => $file ) {
self::$$v = CSSCompression::getJSON( $file );
}
}
}
/**
* Central handler for all color conversions.
*
* @param (string) val: Color to be parsed
*/
public function color( $val ) {
// Converts rgb values to hex codes
if ( $this->options['color-rgb2hex'] ) {
$val = $this->rgb2hex( $val );
}
// Convert long color names to hex codes
if ( $this->options['color-long2hex'] ) {
$val = $this->color2hex( $val );
}
// Ensure all hex codes are lowercase
if ( preg_match( $this->rhex, $val ) ) {
$val = strtolower( $val );
}
// Convert large hex codes to small codes
if ( $this->options['color-hex2shorthex'] ) {
$val = $this->hex2short( $val );
}
// Convert 6 digit hex codes to short color names
if ( $this->options['color-hex2shortcolor'] ) {
$val = $this->hex2color( $val );
}
// Convert safe css level1 color names
if ( $this->options['color-hex2safe'] ) {
$val = $this->hex2safe( $val );
}
return $val;
}
/**
* Converts rgb values to hex codes
*
* @param (string) val: Color to be converted
*/
private function rgb2hex( $val ) {
if ( ! preg_match( $this->rrgb, $val, $match ) ) {
return $val;
}
// locals
$hex = '0123456789abcdef';
$str = explode( ',', $match[ 1 ] );
$new = '';
// Incase rgb was defined with single val
if ( ! $str ) {
$str = array( $match[ 1 ] );
}
foreach ( $str as $x ) {
$x = strpos( $x, '%' ) !== false ? intval( ( intval( $x ) / 100 ) * 255 ) : intval( $x );
if ( $x > 255 ) {
$x = 255;
}
if ( $x < 0 ) {
$x = 0;
}
$new .= $hex[ ( $x - $x % 16 ) / 16 ];
$new .= $hex[ $x % 16 ];
}
// Repeat hex code to complete 6 digit hex requirement for single definitions
if ( count( $str ) == 1 ) {
$new .= $new . $new;
}
// Replace with hex value
return "#$new";
}
/**
* Convert long color names to hex codes
*
* @param (string) val: Color to be converted
*/
private function color2hex( $val ) {
return isset( self::$color2hex[ $val ] ) ? self::$color2hex[ $val ] : $val;
}
/**
* Convert large hex codes to small codes
*
* @param (string) val: Hex to be shortened
*/
private function hex2short( $val ) {
if ( ! preg_match( $this->rfullhex, $val, $match ) ) {
return $val;
}
// See if we can convert to 3 char hex
$hex = $match[ 1 ];
if ( $hex[ 0 ] == $hex[ 1 ] && $hex[ 2 ] == $hex[ 3 ] && $hex[ 4 ] == $hex[ 5 ] ) {
$val = '#' . $hex[ 0 ] . $hex[ 2 ] . $hex[ 4 ];
}
return $val;
}
/**
* Convert large hex codes to small codes
*
* @param (string) val: Color to be converted
*/
private function hex2color( $val ) {
return isset( self::$hex2short[ $val ] ) ? self::$hex2short[ $val ] : $val;
}
/**
* Convert large hex codes to small codes
*
* @param (string) val: Color to be converted
*/
private function hex2safe( $val ) {
return isset( self::$hex2short_safe[ $val ] ) ? self::$hex2short_safe[ $val ] : $val;
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $args );
}
else {
throw new CSSCompression_Exception( "Unknown method in Color Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,191 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Combine
{
/**
* Combine Patterns
*
* @class Control: Compression Controller
* @param (string) token: Copy of the injection token
* @param (array) options: Reference to options
* @param (regex) rspace: Checks for space without an escape '\' character before it
* @param (regex) rslash: Checks for unescaped slash character
* @param (regex) rimportant: Checking props for uncombinables
* @param (array) methods: List of options with their corresponding class
*/
private $Control;
private $token = '';
private $options = array();
private $rspace = "/(?<!\\\)\s/";
private $rslash = "/(?<!\\\)\//";
private $rimportant = "/inherit|\!important|\!ie|(?<!\\\)\s/i";
private $methods = array(
'csw-combine' => 'BorderOutline',
'border-radius-combine' => 'BorderRadius',
'border-combine' => 'Border',
'mp-combine' => 'MarginPadding',
'background-combine' => 'Background',
'auralcp-combine' => 'Aural',
'font-combine' => 'Font',
'list-combine' => 'List',
);
/**
* Sub Comination Classes
*
* @class BorderOutline: Handles Color/Style/With combinations of border/outline properties
* @class BorderRadius: Handles border-radius combinations
* @class Border: Handles normal border combinations
* @class MarginPadding: Handles margin/padding combinations
* @class Background: Handles background combinations
* @class Aural: Handles aural combinations
* @class Font: Handles font combinations
* @class List: Handles list combinations
* @param (array) subcombines: Array holding all subcombination classes
*/
public $BorderOutline;
public $BorderRadius;
public $Border;
public $MarginPadding;
public $Background;
public $Aural;
public $Font;
public $List;
private $subcombines = array(
'BorderOutline',
'BorderRadius',
'Border',
'MarginPadding',
'Background',
'Aural',
'Font',
'List',
);
/**
* Stash a reference to the controller on each instantiation
*
* @param (class) control: CSSCompression Controller
*/
public function __construct( CSSCompression_Control $control ) {
$this->Control = $control;
$this->token = CSSCompression::TOKEN;
$this->options = &$control->Option->options;
// Include classes if not already done so
if ( ! class_exists( "CSSCompression_Combine_Border", false ) ) {
$path = dirname(__FILE__) . '/Combine/';
foreach ( $this->subcombines as $class ) {
require( $path . $class . '.php' );
}
}
// Instantiate each sub combine
foreach ( $this->subcombines as $class ) {
$full = "CSSCompression_Combine_$class";
$this->$class = new $full( $control, $this );
}
}
/**
* Reads through each detailed package and checks for cross defn combinations
*
* @param (array) selectors: Array of selectors
* @param (array) details: Array of details
*/
public function combine( &$selectors = array(), &$details = array() ) {
foreach ( $details as $i => &$value ) {
if ( isset( $selectors[ $i ] ) && strpos( $selectors[ $i ], $this->token ) === 0 ) {
continue;
}
foreach ( $this->methods as $option => $class ) {
if ( $this->options[ $option ] ) {
$value = $this->$class->combine( $value );
}
}
}
return array( $selectors, $details );
}
/**
* Helper function to ensure flagged words don't get
* overridden
*
* @param (mixed) obj: Array/String of definitions to be checked
*/
public function checkUncombinables( $obj ) {
if ( is_array( $obj ) ) {
foreach ( $obj as $item ) {
if ( preg_match( $this->rimportant, $item ) ) {
return true;
}
}
return false;
}
else {
return preg_match( $this->rimportant, $obj );
}
}
/**
* Helper function to ensure all values of search array
* exist within the storage array
*
* @param (string) prop: CSS Property
* @param (array) storage: Array of definitions found
* @param (array) search: Array of definitions requred
*/
public function searchDefinitions( $prop, $storage, $search ) {
// Return if storage & search don't match
if ( count( $storage ) != count( $search ) ) {
return false;
}
$str = "$prop:";
foreach ( $search as $value ) {
if ( ! isset( $storage[ $value ] ) || $this->checkUncombinables( $storage[ $value ] ) ) {
return false;
}
$str .= $storage[ $value ] . ' ';
}
return trim( $str ) . ';';
}
/**
* Access to private methods for testing
*
* @param (string) subclass: Name of subclass to focus on
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $subclass, $method, $args ) {
if ( $subclass == 'Combine' ) {
if ( method_exists( $this, $method ) ) {
if ( $method == 'combine' ) {
return $this->combine( $args[ 0 ], $args[ 1 ] );
}
else {
return call_user_func_array( array( $this, $method ), $args );
}
}
else {
throw new CSSCompression_Exception( "Unknown method in Combine Class - " . $method );
}
}
else if ( in_array( $subclass, $this->subcombines ) ) {
return $this->$subclass->access( $method, $args );
}
else {
throw new CSSCompression_Exception( "Unknown Sub Combine Class - " . $subclass );
}
}
};
?>

View File

@@ -0,0 +1,109 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Combine_Aural
{
/**
* Combine Patterns
*
* @class Control: Compression Controller
* @class Combine: Combine Controller
* @param (regex) raural: Aurual matching
*/
private $Control;
private $Combine;
private $raural = "/(^|(?<!\\\);)(cue|pause)-(before|after):(.*?)((?<!\\\);|$)/";
/**
* Stash a reference to the controller & combiner
*
* @param (class) control: CSSCompression Controller
* @param (class) combine: CSSCompression Combiner
*/
public function __construct( CSSCompression_Control $control, CSSCompression_Combine $combine ) {
$this->Control = $control;
$this->Combine = $combine;
}
/**
* Combines Aural properties (currently being depreciated in W3C Standards)
*
* @param (string) val: Rule Set
*/
public function combine( $val ) {
$storage = $this->storage( $val );
$pos = 0;
// Replace first occurance with it's prop, and remove all following occurances
while ( preg_match( $this->raural, $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$prop = $match[ 2 ][ 0 ];
if ( isset( $storage[ $prop ] ) ) {
$colon = strlen( $match[ 1 ][ 0 ] );
$val = substr_replace( $val, $storage[ $prop ], $match[ 0 ][ 1 ] + $colon, strlen( $match[ 0 ][ 0 ] ) - $colon );
$pos = $match[ 0 ][ 1 ] + strlen( $storage[ $prop ] ) - $colon - 1;
$storage[ $prop ] = '';
}
else {
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 0 ][ 0 ] ) - 1;
}
}
// Return converted val
return $val;
}
/**
* Builds a storage object for iteration
*
* @param (string) val: Rule Set
*/
private function storage( $val ) {
$storage = array();
// Find all possible occurences and build the replacement
$pos = 0;
while ( preg_match( $this->raural, $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
if ( ! isset( $storage[ $match[ 2 ][ 0 ] ] ) ) {
$storage[ $match[ 2 ][ 0 ] ] = array( $match[ 3 ][ 0 ] => $match[ 4 ][ 0 ] );
}
// Override double written properties
$storage[ $match[ 2 ][ 0 ] ][ $match[ 3 ][ 0 ] ] = $match[ 4 ][ 0 ];
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 0 ][ 0 ] ) - 1;
}
// Go through each tag for possible combination
foreach ( $storage as $tag => $arr ) {
// All three have to be defined
if ( count( $arr ) == 2 && ! $this->Combine->checkUncombinables( $arr ) ) {
$storage[ $tag ] = "$tag:" . $arr['before'] . ' ' . $arr['after'] . ';';
}
else {
unset( $storage[ $tag ] );
}
}
return $storage;
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $args );
}
else {
throw new CSSCompression_Exception( "Unknown method in Aural Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,107 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Combine_Background
{
/**
* Combine Patterns
*
* @class Control: Compression Controller
* @class Combine: Combine Controller
* @param (regex) rbackground: Background matching
* @param (array) groupings: List of background combinations
*/
private $Control;
private $Combine;
private $rbackground = "/(^|(?<!\\\);)background-(color|image|repeat|attachment|position):(.*?)((?<!\\\);|$)/";
private $groupings = array(
// With color
array( 'color', 'image', 'repeat', 'attachment', 'position' ),
array( 'color', 'image', 'attachment', 'position' ),
array( 'color', 'image', 'repeat', 'position' ),
array( 'color', 'image', 'repeat', 'attachment' ),
array( 'color', 'image', 'repeat' ),
array( 'color', 'image', 'attachment' ),
array( 'color', 'image', 'position' ),
array( 'color', 'image' ),
// Without Color
array( 'image', 'attachment', 'position' ),
array( 'image', 'repeat', 'position' ),
array( 'image', 'repeat', 'attachment' ),
array( 'image', 'repeat' ),
array( 'image', 'attachment' ),
array( 'image', 'position' ),
// Just Color/Image
array( 'image' ),
array( 'color' ),
);
/**
* Stash a reference to the controller & combiner
*
* @param (class) control: CSSCompression Controller
* @param (class) combine: CSSCompression Combiner
*/
public function __construct( CSSCompression_Control $control, CSSCompression_Combine $combine ) {
$this->Control = $control;
$this->Combine = $combine;
}
/**
* Combines multiple background props into single definition
*
* @param (string) val: Rule Set
*/
public function combine( $val ) {
$storage = array();
// Find all possible occurences and build the replacement
$pos = 0;
while ( preg_match( $this->rbackground, $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$storage[ $match[ 2 ][ 0 ] ] = $match[ 3 ][ 0 ];
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 0 ][ 0 ] ) - 1;
}
// Run background checks and get replacement str
foreach ( $this->groupings as $props ) {
if ( $replace = $this->Combine->searchDefinitions( 'background', $storage, $props ) ) {
break;
}
}
// If replacement string found, run it on all declarations
if ( $replace ) {
$pos = 0;
while ( preg_match( $this->rbackground, $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$colon = strlen( $match[ 1 ][ 0 ] );
$val = substr_replace( $val, $replace, $match[ 0 ][ 1 ] + $colon, strlen( $match[ 0 ][ 0 ] ) - $colon );
$pos = $match[ 0 ][ 1 ] + strlen( $replace ) - $colon - 1;
$replace = '';
}
}
// Return converted val
return $val;
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $args );
}
else {
throw new CSSCompression_Exception( "Unknown method in Background Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,98 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Combine_Border
{
/**
* Combine Patterns
*
* @class Control: Compression Controller
* @class Combine: Combine Controller
* @param (regex) rborder: Border matching
*/
private $Control;
private $Combine;
private $rborder = "/(^|(?<!\\\);)border-(top|right|bottom|left):(.*?)((?<!\\\);|$)/";
/**
* Stash a reference to the controller & combiner
*
* @param (class) control: CSSCompression Controller
* @param (class) combine: CSSCompression Combiner
*/
public function __construct( CSSCompression_Control $control, CSSCompression_Combine $combine ) {
$this->Control = $control;
$this->Combine = $combine;
}
/**
* Combines multiple border properties into single definition
*
* @param (string) val: Rule Set
*/
public function combine( $val ) {
if ( ( $replace = $this->replace( $val ) ) === false ) {
return $val;
}
// Rebuild the rule set with the combinations found
$pos = 0;
while ( preg_match( $this->rborder, $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$colon = strlen( $match[ 1 ][ 0 ] );
$val = substr_replace( $val, $replace, $match[ 0 ][ 1 ] + $colon, strlen( $match[ 0 ][ 0 ] ) - $colon );
$pos = $match[ 0 ][ 1 ] + strlen( $replace ) - $colon - 1;
$replace = '';
}
// Return converted val
return $val;
}
/**
* Builds a replacement string
*
* @param (string) val: Rule Set
*/
private function replace( $val ) {
$storage = array();
// Find all possible occurences and build the replacement
$pos = 0;
while ( preg_match( $this->rborder, $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
// Override double written properties
$storage[ $match[ 2 ][ 0 ] ] = $match[ 3 ][ 0 ];
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 0 ][ 0 ] ) - 1;
}
// All 4 have to be defined
if ( count( $storage ) == 4 &&
$storage['top'] == $storage['bottom'] &&
$storage['left'] == $storage['right'] &&
$storage['top'] == $storage['right'] ) {
return "border:" . $storage['top'] . ';';
}
return false;
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $args );
}
else {
throw new CSSCompression_Exception( "Unknown method in Border Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,109 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Combine_BorderOutline
{
/**
* Combine Patterns
*
* @class Control: Compression Controller
* @class Combine: Combine Controller
* @param (regex) rcsw: Border/Outline matching
*/
private $Control;
private $Combine;
private $rcsw = "/(^|(?<!\\\);)(border|border-top|border-bottom|border-left|border-right|outline)-(color|style|width):(.*?)((?<!\\\);|$)/";
/**
* Stash a reference to the controller & combiner
*
* @param (class) control: CSSCompression Controller
* @param (class) combine: CSSCompression Combiner
*/
public function __construct( CSSCompression_Control $control, CSSCompression_Combine $combine ) {
$this->Control = $control;
$this->Combine = $combine;
}
/**
* Combines color/style/width of border/outline properties
*
* @param (string) val: Rule Set
*/
public function combine( $val ) {
$storage = $this->storage( $val );
$pos = 0;
// Now rebuild the string replacing all instances
while ( preg_match( $this->rcsw, $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$prop = $match[ 2 ][ 0 ];
if ( isset( $storage[ $prop ] ) ) {
$colon = strlen( $match[ 1 ][ 0 ] );
$val = substr_replace( $val, $storage[ $prop ], $match[ 0 ][ 1 ] + $colon, strlen( $match[ 0 ][ 0 ] ) - $colon );
$pos = $match[ 0 ][ 1 ] + strlen( $storage[ $prop ] ) - $colon - 1;
$storage[ $prop ] = '';
}
else {
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 0 ][ 0 ] ) - 1;
}
}
// Return converted val
return $val;
}
/**
* Builds a storage object for iteration
*
* @param (string) val: Rule Set
*/
private function storage( $val ) {
$storage = array();
$pos = 0;
// Find all possible occurences and build the replacement
while ( preg_match( $this->rcsw, $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
if ( ! isset( $storage[ $match[ 2 ][ 0 ] ] ) ) {
$storage[ $match[ 2 ][ 0 ] ] = array( $match[ 3 ][ 0 ] => $match[ 4 ][ 0 ] );
}
// Override double written properties
$storage[ $match[ 2 ][ 0 ] ][ $match[ 3 ][ 0 ] ] = $match[ 4 ][ 0 ];
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 0 ][ 0 ] ) - 1;
}
// Go through each tag for possible combination
foreach ( $storage as $tag => $arr ) {
// All three have to be defined
if ( count( $arr ) == 3 && ! $this->Combine->checkUncombinables( $arr ) ) {
$storage[ $tag ] = "$tag:" . $arr['width'] . ' ' . $arr['style'] . ' ' . $arr['color'] . ';';
}
else {
unset( $storage[ $tag ] );
}
}
return $storage;
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $args );
}
else {
throw new CSSCompression_Exception( "Unknown method in BorderOutline Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,263 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Combine_BorderRadius
{
/**
* Combine Patterns
*
* @class Control: Compression Controller
* @class Combine: Combine Controller
* @param (regex) rspace: Checks for space without an escape '\' character before it
* @param (regex) rslash: Checks for unescaped slash character
* @param (array) borderRadius: Various border radii components
*/
private $Control;
private $Combine;
private $rspace = "/(?<!\\\)\s/";
private $rslash = "/(?<!\\\)\//";
private $borderRadius = array(
'css3' => array(
'mod' => '',
'base' => "/(^|(?<!\\\);)border-radius:(.*?)((?<!\\\);|$)/",
'full' => "/(^|(?<!\\\);)border-(top|bottom)-(left|right)-radius:(.*?)((?<!\\\);|$)/",
),
'moz' => array(
'mod' => '-moz-',
'base' => "/(^|(?<!\\\);)-moz-border-radius:(.*?)((?<!\\\);|$)/",
'full' => "/(^|(?<!\\\);)-moz-border-radius-(top|bottom)(left|right):(.*?)((?<!\\\);|$)/"
),
'webkit' => array(
'mod' => '-webkit-',
'base' => "/(^|(?<!\\\);)-webkit-border-radius:(.*?)((?<!\\\);|$)/",
'full' => "/(^|(?<!\\\);)-webkit-border-(top|bottom)-(left|right)-radius:(.*?)((?<!\\\);|$)/"
),
);
/**
* Stash a reference to the controller & combiner
*
* @param (class) control: CSSCompression Controller
* @param (class) combine: CSSCompression Combiner
*/
public function __construct( CSSCompression_Control $control, CSSCompression_Combine $combine ) {
$this->Control = $control;
$this->Combine = $combine;
}
/**
* Main handler to combine border-radii into a single rule
*
* @param (string) val: Rule Set
*/
public function combine( $val ) {
foreach ( $this->borderRadius as $regex ) {
$val = $this->fix( $val, $regex );
}
return $val;
}
/**
* Does the actual combining
*
* @param (string) val: Rule Set
*/
private function fix( $val, $regex ) {
$val = $this->base( $val, $regex );
$replace = $regex['mod'];
// Storage builder
if ( ( $storage = $this->storage( $val, $regex ) ) === false ) {
return $val;
}
// Setup horizontal/vertical radii
foreach ( $storage as $dir => &$config ) {
// Verticals are optional
if ( $dir == 'vertical' && ! $config['keep'] ) {
break;
}
// All 4 are the same
else if ( $config['top-left'] == $config['top-right'] &&
$config['top-right'] == $config['bottom-right'] &&
$config['bottom-right'] == $config['bottom-left'] ) {
$config['replace'] .= $config['top-left'];
}
// Opposites are the same
else if ( $config['top-left'] == $config['bottom-right'] && $config['top-right'] == $config['bottom-left'] ) {
$config['replace'] .= $config['top-left'] . ' ' . $config['top-right'];
}
// 3-point directional
else if ( $config['top-right'] == $config['bottom-left'] ) {
$config['replace'] .= $config['top-left'] . ' ' . $config['top-right'] . ' ' . $config['bottom-right'];
}
// none are the same, but can still use shorthand notation
else {
$config['replace'] .= $config['top-left'] . ' ' . $config['top-right'] . ' '
. $config['bottom-right'] . ' ' . $config['bottom-left'];
}
}
// Now rebuild the string replacing all instances of margin/padding if shorthand exists
$pos = 0;
$replace = $regex['mod'] . "border-radius:" . $storage['horizontal']['replace'] . $storage['vertical']['replace'] . ';';
while ( preg_match( $regex['full'], $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$colon = strlen( $match[ 1 ][ 0 ] );
$val = substr_replace( $val, $replace, $match[ 0 ][ 1 ] + $colon, strlen( $match[ 0 ][ 0 ] ) - $colon );
$pos = $match[ 0 ][ 1 ] + strlen( $replace ) - $colon - 1;
$replace = '';
}
// Return converted val
return $val;
}
/**
* Expands short handed border radius props for combination
*
* @param (string) val: Rule Set
*/
private function base( $val, $regex ) {
$pos = 0;
while ( preg_match( $regex['base'], $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$replace = '';
$colon = strlen( $match[ 1 ][ 0 ] );
$parts = preg_split( $this->rslash, trim( $match[ 2 ][ 0 ] ), 2 );
$positions = array(
'top-left' => 0,
'top-right' => 0,
'bottom-right' => 0,
'bottom-left' => 0,
);
$base = array(
'horizontal' => array(
'parts' => preg_split( $this->rspace, trim( $parts[ 0 ] ) ),
'pos' => $positions,
),
'vertical' => array(
'parts' => isset( $parts[ 1 ] ) ? preg_split( $this->rspace, trim( $parts[ 1 ] ) ) : '',
'pos' => $positions,
),
);
foreach ( $base as &$config ) {
// Skip uncombinables
if ( $this->Combine->checkUncombinables( $config['parts'] ) ) {
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 0 ][ 0 ] ) - 1;
continue 2;
}
// Might not have verticals
else if ( $config['parts'] === '' ) {
continue;
}
// Each position needs a value
switch ( count( $config['parts'] ) ) {
case 1:
$config['pos']['top-left'] = $config['pos']['top-right'] = $config['parts'][ 0 ];
$config['pos']['bottom-left'] = $config['pos']['bottom-right'] = $config['parts'][ 0 ];
break;
case 2:
$config['pos']['top-left'] = $config['pos']['bottom-right'] = $config['parts'][ 0 ];
$config['pos']['bottom-left'] = $config['pos']['top-right'] = $config['parts'][ 1 ];
break;
case 3:
$config['pos']['top-left'] = $config['parts'][ 0 ];
$config['pos']['bottom-left'] = $config['pos']['top-right'] = $config['parts'][ 1 ];
$config['pos']['bottom-right'] = $config['parts'][ 2 ];
break;
case 4:
$config['pos']['top-left'] = $config['parts'][ 0 ];
$config['pos']['top-right'] = $config['parts'][ 1 ];
$config['pos']['bottom-right'] = $config['parts'][ 2 ];
$config['pos']['bottom-left'] = $config['parts'][ 3 ];
break;
default:
continue 2;
}
}
// Build the replacement
foreach ( $positions as $p => $v ) {
if ( $regex['mod'] == '-moz-' ) {
$replace .= "-moz-border-radius-" . preg_replace( "/-/", '', $p ) . ":"
. $base['horizontal']['pos'][ $p ]
. ( $base['vertical']['parts'] === '' ? '' : ' ' . $base['vertical']['pos'][ $p ] )
. ';';
}
else {
$replace .= $regex['mod'] . "border-$p-radius:"
. $base['horizontal']['pos'][ $p ]
. ( $base['vertical']['parts'] === '' ? '' : ' ' . $base['vertical']['pos'][ $p ] )
. ';';
}
}
$pos += strlen( $replace );
$val = substr_replace( $val, $replace, $match[ 0 ][ 1 ] + $colon, strlen( $match[ 0 ][ 0 ] ) - $colon );
}
return $val;
}
/**
* Builds the storage object for border radius props
*
* @param (string) val: Rule Set
* @param (array) regex: Current border radius type checking props
*/
private function storage( $val, $regex ) {
$storage = array(
'horizontal' => array( 'replace' => '' ),
'vertical' => array( 'replace' => '', 'keep' => false ),
);
// Find all possible occurences of this border-radius type and mark their directional value
$pos = 0;
while ( preg_match( $regex['full'], $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 0 ][ 0 ] ) - 1;
$parts = preg_split( $this->rspace, $match[ 4 ][ 0 ], 2 );
$storage['horizontal'][ $match[ 2 ][ 0 ] . '-' . $match[ 3 ][ 0 ] ] = trim( $parts[ 0 ] );
if ( isset( $parts[ 1 ] ) ) {
$storage['vertical'][ $match[ 2 ][ 0 ] . '-' . $match[ 3 ][ 0 ] ] = trim( $parts[ 1 ] );
$storage['vertical']['keep'] = true;
$storage['vertical']['replace'] = '/';
}
else {
$storage['vertical'][ $match[ 2 ][ 0 ] . '-' . $match[ 3 ][ 0 ] ] = '0';
}
}
// Only combine if all 4 definitions are found (5 including replace)
if ( count( $storage['horizontal'] ) != 5 ||
$this->Combine->checkUncombinables( $storage['horizontal'] ) ||
$this->Combine->checkUncombinables( $storage['vertical'] ) ) {
return false;
}
return $storage;
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $args );
}
else {
throw new CSSCompression_Exception( "Unknown method in BorderRadius Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,125 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Combine_Font
{
/**
* Combine Patterns
*
* @class Control: Compression Controller
* @class Combine: Combine Controller
* @param (regex) rfont: Font matching
* @param (array) groupings: Set of font combinationals
*/
private $Control;
private $Combine;
private $rfont = "/(^|(?<!\\\);)(font|line)-(style|variant|weight|size|height|family):(.*?)((?<!\\\);|$)/";
private $groupings = array(
array( 'font-style', 'font-variant', 'font-weight', 'size/height', 'font-family' ),
array( 'font-style', 'font-variant', 'font-weight', 'font-size', 'font-family' ),
array( 'font-style', 'font-variant', 'size/height', 'font-family' ),
array( 'font-style', 'font-variant', 'font-size', 'font-family' ),
array( 'font-style', 'font-weight', 'size/height', 'font-family' ),
array( 'font-style', 'font-weight', 'font-size', 'font-family' ),
array( 'font-variant', 'font-weight', 'size/height', 'font-family' ),
array( 'font-variant', 'font-weight', 'font-size', 'font-family' ),
array( 'font-weight', 'size/height', 'font-family' ),
array( 'font-weight', 'font-size', 'font-family' ),
array( 'font-variant', 'size/height', 'font-family' ),
array( 'font-variant', 'font-size', 'font-family' ),
array( 'font-style', 'size/height', 'font-family' ),
array( 'font-style', 'font-size', 'font-family' ),
array( 'size/height', 'font-family' ),
array( 'font-size', 'font-family' ),
);
/**
* Stash a reference to the controller & combiner
*
* @param (class) control: CSSCompression Controller
* @param (class) combine: CSSCompression Combiner
*/
public function __construct( CSSCompression_Control $control, CSSCompression_Combine $combine ) {
$this->Control = $control;
$this->Combine = $combine;
}
/**
* Combines multiple font-definitions into single definition
*
* @param (string) val: Rule Set
*/
public function combine( $val ) {
$storage = $this->storage( $val );
// Loop through each property check and see if they can be replaced
foreach ( $this->groupings as $props ) {
if ( $replace = $this->Combine->searchDefinitions( 'font', $storage, $props ) ) {
break;
}
}
// If replacement string found, run it on all declarations
if ( $replace ) {
$pos = 0;
while ( preg_match( $this->rfont, $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
if ( ! isset( $storage['line-height'] ) && stripos( $match[ 0 ][ 0 ], 'line-height') === 0 ) {
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 0 ][ 0 ] ) - 1;
continue;
}
$colon = strlen( $match[ 1 ][ 0 ] );
$val = substr_replace( $val, $replace, $match[ 0 ][ 1 ] + $colon, strlen( $match[ 0 ][ 0 ] ) - $colon );
$pos = $match[ 0 ][ 1 ] + strlen( $replace ) - $colon - 1;
$replace = '';
}
}
// Return converted val
return $val;
}
/**
* Builds a storage object for iteration
*
* @param (string) val: Rule Set
*/
private function storage( $val ) {
$storage = array();
// Find all possible occurences and build the replacement
$pos = 0;
while ( preg_match( $this->rfont, $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$storage[ $match[ 2 ][ 0 ] . '-' . $match[ 3 ][ 0 ] ] = $match[ 4 ][ 0 ];
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 0 ][ 0 ] ) - 1;
}
// Combine font-size & line-height if possible
if ( isset( $storage['font-size'] ) && isset( $storage['line-height'] ) ) {
$storage['size/height'] = $storage['font-size'] . '/' . $storage['line-height'];
unset( $storage['font-size'], $storage['line-height'] );
}
return $storage;
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $args );
}
else {
throw new CSSCompression_Exception( "Unknown method in Font Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,104 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Combine_List
{
/**
* Combine Patterns
*
* @class Control: Compression Controller
* @class Combine: Combine Controller
* @param (regex) rlist: List style matching
* @param (array) groupings: Group of list combinationals
*/
private $Control;
private $Combine;
private $rlist = "/(^|(?<!\\\);)list-style-(type|position|image):(.*?)((?<!\\\);|$)/";
private $groupings = array(
array( 'type', 'position', 'image' ),
array( 'type', 'position' ),
array( 'type', 'image' ),
array( 'position', 'image' ),
array( 'type' ),
array( 'position' ),
array( 'image' ),
);
/**
* Stash a reference to the controller & combiner
*
* @param (class) control: CSSCompression Controller
* @param (class) combine: CSSCompression Combiner
*/
public function __construct( CSSCompression_Control $control, CSSCompression_Combine $combine ) {
$this->Control = $control;
$this->Combine = $combine;
}
/**
* Combines multiple list style props into single definition
*
* @param (string) val: Rule Set
*/
public function combine( $val ) {
// If replacement string found, run it on all declarations
if ( ( $replace = $this->replace( $val ) ) !== false ) {
$pos = 0;
while ( preg_match( $this->rlist, $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$colon = strlen( $match[ 1 ][ 0 ] );
$val = substr_replace( $val, $replace, $match[ 0 ][ 1 ] + $colon, strlen( $match[ 0 ][ 0 ] ) - $colon );
$pos = $match[ 0 ][ 1 ] + strlen( $replace ) - $colon - 1;
$replace = '';
}
}
// Return converted val
return $val;
}
/**
* Build the replacement string for list props
*
* @param (string) val: Rule Set
*/
private function replace( $val ) {
$storage = array();
$pos = 0;
// Find all possible occurences and build the replacement
while ( preg_match( $this->rlist, $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$storage[ $match[ 2 ][ 0 ] ] = $match[ 3 ][ 0 ];
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 0 ][ 0 ] ) - 1;
}
// Run background checks and get replacement str
foreach ( $this->groupings as $props ) {
if ( $replace = $this->Combine->searchDefinitions( 'list-style', $storage, $props ) ) {
return $replace;
}
}
return false;
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $args );
}
else {
throw new CSSCompression_Exception( "Unknown method in List Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,190 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Combine_MarginPadding
{
/**
* Combine Patterns
*
* @class Control: Compression Controller
* @class Combine: Combine Controller
* @param (regex) rspace: Checks for space without an escape '\' character before it
* @param (regex) rmp: Margin/Padding matching
* @param (regex) rmpbase: Margin/Padding base match
*/
private $Control;
private $Combine;
private $rspace = "/(?<!\\\)\s/";
private $rmp = "/(^|(?<!\\\);)(margin|padding)-(top|right|bottom|left):(.*?)((?<!\\\);|$)/";
private $rmpbase = "/(^|(?<!\\\);)(margin|padding):(.*?)((?<!\\\);|$)/";
/**
* Stash a reference to the controller & combiner
*
* @param (class) control: CSSCompression Controller
* @param (class) combine: CSSCompression Combiner
*/
public function __construct( CSSCompression_Control $control, CSSCompression_Combine $combine ) {
$this->Control = $control;
$this->Combine = $combine;
}
/**
* Combines multiple directional properties of
* margin/padding into single definition.
*
* @param (string) val: Rule Set
*/
public function combine( $val ) {
$val = $this->expand( $val );
$storage = $this->storage( $val );
$pos = 0;
// Now rebuild the string replacing all instances of margin/padding if shorthand exists
while ( preg_match( $this->rmp, $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$prop = $match[ 2 ][ 0 ];
if ( isset( $storage[ $prop ] ) ) {
$colon = strlen( $match[ 1 ][ 0 ] );
$val = substr_replace( $val, $storage[ $prop ], $match[ 0 ][ 1 ] + $colon, strlen( $match[ 0 ][ 0 ] ) - $colon );
$pos = $match[ 0 ][ 1 ] + strlen( $storage[ $prop ] ) - $colon - 1;
$storage[ $prop ] = '';
}
else {
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 0 ][ 0 ] ) - 1;
}
}
// Return converted val
return $val;
}
/**
* Build the storage object for iteration
*
* @param (string) val: Rule Set
*/
private function storage( $val ) {
$storage = array();
$pos = 0;
// Find all possible occurences of margin/padding and mark their directional value
while ( preg_match( $this->rmp, $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
if ( ! isset( $storage[ $match[ 2 ][ 0 ] ] ) ) {
$storage[ $match[ 2 ][ 0 ] ] = array( $match[ 3 ][ 0 ] => $match[ 4 ][ 0 ] );
}
// Override double written properties
$storage[ $match[ 2 ][ 0 ] ][ $match[ 3 ][ 0 ] ] = $match[ 4 ][ 0 ];
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 0 ][ 0 ] ) - 1;
}
// Go through each tag for possible combination
foreach ( $storage as $tag => $arr ) {
// Only combine if all 4 definitions are found
if ( count( $arr ) == 4 && ! $this->Combine->checkUncombinables( $arr ) ) {
// All 4 are the same
if ( $arr['top'] == $arr['bottom'] && $arr['left'] == $arr['right'] && $arr['top'] == $arr['left'] ) {
$storage[ $tag ] = "$tag:" . $arr['top'] . ';';
}
// Opposites are the same
else if ( $arr['top'] == $arr['bottom'] && $arr['left'] == $arr['right'] ) {
$storage[ $tag ] = "$tag:" . $arr['top'] . ' ' . $arr['left'] . ';';
}
// 3-point directional
else if ( $arr['right'] == $arr['left'] ) {
$storage[ $tag ] = "$tag:" . $arr['top'] . ' ' . $arr['right'] . ' ' . $arr['bottom'] . ';';
}
// none are the same, but can still use shorthand notation
else {
$storage[ $tag ] = "$tag:" . $arr['top'] . ' ' . $arr['right'] . ' ' . $arr['bottom'] . ' ' . $arr['left'] . ';';
}
}
else {
unset( $storage[ $tag ] );
}
}
return $storage;
}
/**
* Explodes shorthanded margin/padding properties for later combination
*
* @param (string) val: Rule set
*/
private function expand( $val ) {
$pos = 0;
while ( preg_match( $this->rmpbase, $val, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$replace = '';
$prop = $match[ 2 ][ 0 ];
$value = preg_split( $this->rspace, trim( $match[ 3 ][ 0 ] ) );
$positions = array(
'top' => 0,
'right' => 0,
'bottom' => 0,
'left' => 0
);
// Skip uncombinables
if ( $this->Combine->checkUncombinables( $value ) ) {
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 0 ][ 0 ] );
continue;
}
// Each position needs a value
switch ( count( $value ) ) {
case 1:
$positions['top'] = $positions['right'] = $positions['bottom'] = $positions['left'] = $value[ 0 ];
break;
case 2:
$positions['top'] = $positions['bottom'] = $value[ 0 ];
$positions['right'] = $positions['left'] = $value[ 1 ];
break;
case 3:
$positions['top'] = $value[ 0 ];
$positions['right'] = $positions['left'] = $value[ 1 ];
$positions['bottom'] = $value[ 2 ];
break;
case 4:
$positions['top'] = $value[ 0 ];
$positions['right'] = $value[ 1 ];
$positions['bottom'] = $value[ 2 ];
$positions['left'] = $value[ 3 ];
break;
default:
continue;
}
// Build the replacement
foreach ( $positions as $p => $v ) {
$replace .= "$prop-$p:$v;";
}
$colon = strlen( $match[ 1 ][ 0 ] );
$val = substr_replace( $val, $replace, $match[ 0 ][ 1 ] + $colon, strlen( $match[ 0 ][ 0 ] ) - $colon );
$pos = $match[ 0 ][ 1 ] + strlen( $replace ) - $colon - 1;
}
return $val;
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $args );
}
else {
throw new CSSCompression_Exception( "Unknown method in MarginPadding Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,212 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Compress
{
/**
* Trim Patterns
*
* @param (array) options: Reference to options
* @param (array) stats: Reference to stats
* @param (regex) rsemicolon: Checks for semicolon without an escape '\' character before it
* @param (regex) rcolon: Checks for colon without an escape '\' character before it
* @param (regex) rspace: Checks for space without an escape '\' character before it
*/
private $options = array();
private $stats = array();
private $rsemicolon = "/(?<!\\\);/";
private $rcolon = "/(?<!\\\):/";
private $rspace = "/(?<!\\\)\s/";
/**
* Other inner classes that get used within compression
*
* @class Control: Compression Controller
* @class Trim: Trim Instance
* @class Setup: Setup Instance
* @class Format: Formatting Instance
* @class Combine: Combine Instance
* @class Cleanup: Cleanup Instance
* @class Organize: Organize Instance
* @class Selectors: Selectors Instance
* @param (array) others: List of above classes for copying
*/
private $Control;
private $Trim;
private $Setup;
private $Format;
private $Combine;
private $Cleanup;
private $Organize;
private $Selectors;
private $others = array(
'Trim',
'Setup',
'Format',
'Combine',
'Cleanup',
'Organize',
'Selectors',
);
/**
* Stash a reference to the controller on each instantiation
*
* @param (class) control: CSSCompression Controller
*/
public function __construct( CSSCompression_Control $control ) {
$this->Control = $control;
$this->options = &$control->Option->options;
$this->stats = &$control->stats;
foreach ( $this->others as $class ) {
$this->$class = $control->$class;
}
}
/**
* Centralized function to run css compression.
*
* @param (string) css: Stylesheet to compresss
*/
public function compress( $css ) {
$setup = $this->setup( $css );
$setup = $this->rulesets( $setup );
$css = $this->readability( $setup );
// Attach plea to top of page with unknown blocks
if ( $this->options['add-unknown'] && count( $setup['unknown'] ) ) {
$css = "/*\nThere are unknown blocks in the sheet, please please please open an issue with your sheet attached to it:\n"
. "https://github.com/codenothing/css-compressor/issues\n"
. "Thank You --\n\n"
. implode( "\n", $setup['unknown'] )
. "\n*/\n"
. $css;
}
// Mark final file size
$this->stats['after']['size'] = strlen( $css = trim( $css ) );
// Return compressed css
return $css;
}
/**
* Runs css through initial setup handlers
*
* @param (string) css: Sheet to compress
*/
private function setup( $css ) {
// Initial stats
$this->stats['before']['time'] = microtime( true );
$this->stats['before']['size'] = strlen( $css );
// Initial trimming
$css = $this->Trim->trim( $css );
// Do a little tokenizing, compress each property individually
$setup = $this->Setup->setup( $css );
// Mark number of selectors pre-combine
$this->stats['before']['selectors'] = count( $setup['selectors'] );
return $setup;
}
/**
* Focus compressions on each rule set
*
* @param (array) setup: Array containing selectors and rule sets
*/
private function rulesets( $setup ) {
// Do selector specific compressions
$this->Selectors->selectors( $setup['selectors'] );
// Look at each group of properties as a whole, and compress/combine similiar definitions
$this->Combine->combine( $setup['selectors'], $setup['details'] );
// If order isn't important, run comination functions before and after compressions to catch all instances
// Be sure to prune before hand for higher chance of matching
if ( $this->options['organize'] ) {
$this->Cleanup->cleanup( $setup['selectors'], $setup['details'] );
$this->Organize->organize( $setup['selectors'], $setup['details'] );
$this->Combine->combine( $setup['selectors'], $setup['details'] );
}
// Do final maintenace work, remove injected property/values
$this->Cleanup->cleanup( $setup['selectors'], $setup['details'] );
// Run final counters before full cleanup
$this->finalCount( $setup['selectors'], $setup['details'] );
return $setup;
}
/**
* Runs final counts on selectors and props
*
* @param (array) selectors: Selector rules
* @param (array) details: Rule sets
*/
private function finalCount( $selectors, $details ) {
// Selectors and props
$this->stats['after']['selectors'] = count( $selectors );
foreach ( $details as $item ) {
$props = preg_split( $this->rsemicolon, $item );
// Make sure count is true
foreach ( $props as $k => $v ) {
if ( ! isset( $v ) || $v == '' ) {
unset( $props[ $k ] );
}
}
$this->stats['after']['props'] += count( $props );
}
// Final count for stats
$this->stats['after']['time'] = microtime( true );
}
/**
* Formats the compressed rule sets into a stylesheet
*
* @param (array) setup: Array containing selectors and rule sets
*/
private function readability( $setup ) {
// Format css to users preference
$css = $this->Format->readability( $this->options['readability'], $setup['selectors'], $setup['details'] );
// Intros
foreach ( $setup as $value ) {
if ( $value && is_string( $value ) ) {
$css = $value . $css;
}
}
// Remove escapables
$css = $this->Cleanup->removeInjections( $css );
return $css;
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $args );
}
else {
throw new CSSCompression_Exception( "Unknown method in Compress Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,236 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Control
{
/**
* Control Patterns
*
* @param (string) css: Holds compressed css string
* @param (string) mode: Current compression mode state
* @param (array) stats: Holds compression stats
* @param (array) getters: Array of accessible getters
*/
public $css = '';
public $mode = '';
public $stats = array();
private $getters = array(
'css',
'mode',
'stats',
);
/**
* Subclasses that do the ground work for this compressor
*
* @class CSSCompression: Public facing compression class
* @class Option: Option handling
* @class Trim: Does the initial trimming for the css
* @class Format: Formats the output
* @class Numeric: Handles numeric compression
* @class Color: Handles color compression
* @class Individuals: Runs compression algorithms on individual properties and values
* @class Selectors: Runs selector specific compressions
* @class Combine: Handles combining of various properties
* @class Organize: Reorganizes the sheet for futher compression
* @class Cleanup: Cleans out all injected characters during compression
* @class Compress: Central compression unit.
* @param (array) subclasses: Array holding all the subclasses for inlusion
*/
public $CSSCompression;
public $Option;
public $Trim;
public $Format;
public $Numeric;
public $Color;
public $Individuals;
public $Selectors;
public $Combine;
public $Organize;
public $Cleanup;
public $Setup;
public $Compress;
private $subclasses = array(
'Option',
'Trim',
'Format',
'Numeric',
'Color',
'Individuals',
'Selectors',
'Combine',
'Organize',
'Cleanup',
'Setup',
'Compress',
);
/**
* Pull in the Compression instance and build the subclasses
*
* @param (class) CSSCompression: CSSCompression Instance
*/
public function __construct( CSSCompression $CSSCompression ) {
$this->CSSCompression = $CSSCompression;
// Load all subclasses on demand
if ( ! class_exists( "CSSCompression_Option", false ) ) {
$path = dirname(__FILE__) . '/';
foreach ( $this->subclasses as $class ) {
require( $path . $class . '.php' );
}
}
// Initialize each subclass
foreach ( $this->subclasses as $class ) {
$full = "CSSCompression_$class";
$this->$class = new $full( $this );
}
}
/**
* Control access to properties
*
* - Getting stats/mode/css returns the current value of that property
* - Getting options will return the current full options array
* - Getting anything else returns that current value in the options array or NULL
*
* @param (string) name: Name of property that you want to access
*/
public function get( $name ) {
if ( in_array( $name, $this->getters ) ) {
return $this->$name;
}
else if ( $name == 'options' ) {
return $this->Option->options;
}
else {
return $this->Option->option( $name );
}
}
/**
* The setter method only allows access to setting values in the options array
*
* @param (string) name: Key name of the option you want to set
* @param (mixed) value: Value of the option you want to set
*/
public function set( $name, $value ) {
// Allow for passing array of options to merge into current ones
if ( $name === 'options' && is_array( $value ) ) {
return $this->Option->merge( $value );
}
else if ( isset( CSSCompression::$defaults[ $name ] ) ) {
return $this->Option->option( $name, $value );
}
else {
throw new CSSCompression_Exception( "Invalid Private Access to $name in CSSCompression." );
}
}
/**
* Merges a predefined set options
*
* @param (string) mode: Name of mode to use.
*/
public function mode( $mode = NULL ) {
return $this->Options->merge( $mode );
}
/**
* Resets options to their defaults, and flushes out variables
*
* @params none
*/
public function reset(){
$this->Option->reset();
return $this->flush();
}
/**
* Cleans out class variables for next run
*
* @params none
*/
public function flush(){
$this->css = '';
$this->stats = array(
'before' => array(
'props' => 0,
'selectors' => 0,
'size' => 0,
'time' => 0,
),
'after' => array(
'props' => 0,
'selectors' => 0,
'size' => 0,
'time' => 0,
),
);
return true;
}
/**
* Proxy to run Compression on the sheet passed. Handle options here.
*
* @param (string) css: Stylesheet to be compressed
* @param (mixed) options: Array of options or mode to use.
*/
public function compress( $css = NULL, $options = NULL ) {
// Flush out old stats and variables
$this->flush();
// If no additional options, just run compression
if ( $options === NULL ) {
return $this->css = $this->Compress->compress( $css );
}
// Store old params
$old = $this->mode == '__custom' ? $this->Option->option() : $this->mode;
$readability = $this->Option->option( 'readability' );
// Compress with new set of options
$this->Option->merge( $options );
$css = $this->Compress->compress( $css );
// Reset original options
$this->reset();
$this->Option->merge( $old );
// Return the compressed css
return $this->css = $css;
}
/**
* Backdoor access to subclasses
* ONLY FOR DEVELOPMENT/TESTING.
*
* @param (string) class: Name of the focus class
* @param (array) config: Contains name reference and test arguments
*/
public function access( $class, $method, $args ) {
if ( $class == 'Control' ) {
return call_user_func_array( array( $class, $method ), $args );
}
else if ( strpos( $class, '.' ) !== false ) {
$parts = explode( '.', $class );
$class = $parts[ 0 ];
$subclass = $parts[ 1 ];
return $this->$class->access( $subclass, $method, $args );
}
else if ( in_array( $class, $this->subclasses ) ) {
return $this->$class->access( $method, $args );
}
else {
throw new CSSCompression_Exception( "Unknown Class Access - " . $class );
}
}
};
?>

View File

@@ -0,0 +1,32 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Exception extends Exception
{
/**
* Custom exception handler
*
* @param (string) message: Error message
* @param (int) code: Error code
* @instance (Exception Instance) previous: Previous exception
*/
public function __construct( $message = 'Unknown Exception', $code = 0, Exception $previous = NULL ) {
parent::__construct( $message, $code, $previous );
}
/**
* String version of this custom exception
*
* @params none
*/
public function __toString(){
return "CSSCompression Exception: [" . $this->code . "] " . $this->message . "\n";
}
};
?>

View File

@@ -0,0 +1,187 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Format
{
/**
* Format Patterns
*
* @class Control: Compression Controller
* @param (string) token: Copy of the injection token
* @param (array) options: Reference to options
* @param (regex) rsemicolon: Checks for semicolon without an escape '\' character before it
* @param (regex) rcolon: Checks for colon without an escape '\' character before it
* @param (array) readability: Mapping to readability functions
*/
private $Control;
private $token = '';
private $options = array();
private $rsemicolon = "/(?<!\\\);/";
private $rcolon = "/(?<!\\\):/";
private $readability = array(
CSSCompression::READ_MAX => 'maximum',
CSSCompression::READ_MED => 'medium',
CSSCompression::READ_MIN => 'minimum',
CSSCompression::READ_NONE => 'none',
);
/**
* Stash a reference to the controller on each instantiation
*
* @param (class) control: CSSCompression Controller
*/
public function __construct( CSSCompression_Control $control ) {
$this->Control = $control;
$this->token = CSSCompression::TOKEN;
$this->options = &$control->Option->options;
}
/**
* Reformats compressed CSS into specified format
*
* @param (int) readability: Readability level of compressed output
* @param (array) selectors: Array of selectors
* @param (array) details: Array of declarations
*/
public function readability( $readability = CSSCompression::READ_NONE, $selectors = array(), $details = array() ) {
if ( isset( $this->readability[ $readability ] ) ) {
$fn = $this->readability[ $readability ];
return trim( $this->$fn( $selectors, $details ) );
}
else {
return 'Invalid Readability Value';
}
}
/**
* Returns maxium readability, breaking on every selector, brace, and property
*
* @param (array) selectors: Array of selectors
* @param (array) details: Array of declarations
*/
private function maximum( $selectors, $details ) {
$css = '';
foreach ( $selectors as $k => $v ) {
if ( strpos( $v, $this->token ) === 0 ) {
$css .= substr( $v, strlen( $this->token ) );
$css .= $details[ $k ];
continue;
}
else if ( ! $details[ $k ] || trim( $details[ $k ] ) == '' ) {
continue;
}
$v = str_replace( '>', ' > ', $v );
$v = str_replace( '+', ' + ', $v );
$v = str_replace( ',', ', ', $v );
$css .= "$v {\n";
$arr = preg_split( $this->rsemicolon, $details[ $k ] );
foreach ( $arr as $item ) {
if ( ! $item ) {
continue;
}
list( $prop, $val ) = preg_split( $this->rcolon, $item, 2 );
$css .= "\t$prop: $val;\n";
}
// Kill that last semicolon at users request
if ( $this->options['unnecessary-semicolons'] ) {
$css = preg_replace( "/;\n$/", "\n", $css );
}
$css .= "}\n\n";
}
return $css;
}
/**
* Returns medium readability, putting selectors and rule sets on new lines
*
* @param (array) selectors: Array of selectors
* @param (array) details: Array of declarations
*/
private function medium( $selectors, $details ) {
$css = '';
foreach ( $selectors as $k => $v ) {
if ( strpos( $v, $this->token ) === 0 ) {
$css .= substr( $v, strlen( $this->token ) );
$css .= $details[ $k ];
continue;
}
else if ( $details[ $k ] && $details[ $k ] != '' ) {
$css .= "$v {\n\t" . $details[ $k ] . "\n}\n";
}
}
return $css;
}
/**
* Returns minimum readability, breaking after every selector and it's rule set
*
* @param (array) selectors: Array of selectors
* @param (array) details: Array of declarations
*/
private function minimum( $selectors, $details ) {
$css = '';
foreach ( $selectors as $k => $v ) {
if ( strpos( $v, $this->token ) === 0 ) {
$css .= substr( $v, strlen( $this->token ) );
$css .= $details[ $k ];
continue;
}
else if ( $details[ $k ] && $details[ $k ] != '' ) {
$css .= "$v{" . $details[ $k ] . "}\n";
}
}
return $css;
}
/**
* Returns an unreadable, but fully compressed script
*
* @param (array) selectors: Array of selectors
* @param (array) details: Array of declarations
*/
private function none( $selectors, $details ) {
$css = '';
foreach ( $selectors as $k => $v ) {
if ( strpos( $v, $this->token ) === 0 ) {
$css .= substr( $v, strlen( $this->token ) );
$css .= $details[ $k ];
continue;
}
else if ( $details[ $k ] && $details[ $k ] != '' ) {
$css .= trim( "$v{" . $details[ $k ] . "}" );
}
}
return $css;
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $args );
}
else {
throw new CSSCompression_Exception( "Unknown method in Format Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,307 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Individuals
{
/**
* Individual patterns
*
* @class Control: Compression Controller
* @class Numeric: Numeric handler
* @class Color: Color Handler
* @param (array) options: Reference to options
* @param (regex) rdirectional: Properties that may have multiple directions
* @param (regex) rborderradius: Checks property for border-radius declaration
* @param (regex) rnoneprop: Properties that can have none as their value(will be converted to 0)
* @param (regex) rclip: Looks for rect grouping in clip declaration
* @param (regex) rsplitter: Checks font properties for font-size/line-height split
* @param (regex) rfilter: Special alpha filter for msie
* @param (regex) rspace: Checks for unescaped space
* @param (regex) rspace: Checks for unescaped slash
* @param (array) weights: Array of font-weight name conversions to their numeric counterpart
*/
private $Control;
private $Numeric;
private $Color;
private $options = array();
private $rdirectional = "/^(margin|padding|border-spacing)$/";
private $rborderradius = "/border[a-z-]*radius/";
private $rradiusfull = "/^(-moz-|-webkit-)?border-radius$/";
private $rnoneprop = "/^(border|background|border-(top|right|bottom|left))$/";
private $rclip = "/^rect\(\s*(\-?\d*\.?\d*?\w*)(,|\s)(\-?\d*\.?\d*?\w*)(,|\s)(\-?\d*\.?\d*?\w*)(,|\s)(\-?\d*\.?\d*?\w*)\s*\)$/";
private $rsplitter = "/(^|(?<!\\\)\s)([^\/ ]+)\/([^\/ ]+)((?<!\\\)\s|$)/";
private $rfilter = "/[\"']?PROGID\\\?:DXImageTransform\\\?.Microsoft\\\?.Alpha\(Opacity\\\?=(\d+\\\?\.?\d*)\)[\"']?/i";
private $rspace = "/(?<!\\\)\s/";
private $rslash = "/(?<!\\\)\//";
private $weights = array(
"normal" => 400,
"bold" => 700,
);
/**
* Stash a reference to the controller on each instantiation
*
* @param (class) control: CSSCompression Controller
*/
public function __construct( CSSCompression_Control $control ) {
$this->Control = $control;
$this->Numeric = $control->Numeric;
$this->Color = $control->Color;
$this->options = &$control->Option->options;
}
/**
* Runs special unit/directional compressions
*
* @param (string) prop: CSS Property
* @param (string) val: Value of CSS Property
*/
public function individuals( $prop, $val ) {
// Properties should always be lowercase
$prop = strtolower( $prop );
// Split up each definiton for color and numeric compressions
$parts = preg_split( $this->rspace, $val );
foreach ( $parts as &$v ) {
if ( ! $v || $v == '' ) {
continue;
}
// Remove uneeded decimals/units
if ( $this->options['format-units'] ) {
$v = $this->Numeric->numeric( $v );
}
// Color compression
$v = $this->Color->color( $v );
}
$val = trim( implode( ' ', $parts ) );
// Special border radius handling
if ( preg_match( $this->rborderradius, $prop ) ) {
$val = $this->borderRadius( $prop, $val );
}
// Remove uneeded side definitions if possible
else if ( $this->options['directional-compress'] && count( $parts ) > 1 && preg_match( $this->rdirectional, $prop ) ) {
$val = $this->directionals( strtolower( $val ) );
}
// Font-weight converter
if ( $this->options['fontweight2num'] && ( $prop == 'font-weight' || $prop == 'font' ) ) {
$val = $this->fontweight( $val );
}
// Special font value conversions
if ( $prop == 'font' ) {
$val = $this->font( $val );
}
// Special clip value compressions
if ( $prop == 'clip' ) {
$val = $this->clip( $val );
}
// None to 0 converter
$val = $this->none( $prop, $val );
// MSIE Filters
$val = $this->filter( $prop, $val );
// Return for list retrival
return array( $prop, $val );
}
/**
* Preps border radius for directional compression
*
* @param (string) prop: Property Declaration
* @param (string) val: Declaration Value
*/
private function borderRadius( $prop, $val ) {
if ( preg_match( $this->rslash, $val ) ) {
$parts = preg_split( $this->rslash, $val, 2 );
// We have to redo numeric compression because the slash may hav intruded
foreach ( $parts as &$row ) {
$p = preg_split( $this->rspace, $row );
foreach ( $p as &$v ) {
if ( ! $v || $v == '' ) {
continue;
}
// Remove uneeded decimals/units
if ( $this->options['format-units'] ) {
$v = $this->Numeric->numeric( $v );
}
}
$row = implode( ' ', $p );
if ( $this->options['directional-compress'] ) {
$row = $this->directionals( strtolower( $row ) );
}
}
$val = implode( '/', $parts );
}
else if ( $this->options['directional-compress'] && preg_match( $this->rradiusfull, $prop ) ) {
$val = $this->directionals( strtolower( $val ) );
}
return $val;
}
/**
* Finds directional compression on methods like margin/padding
*
* @param (string) val: Value of CSS Property
*/
private function directionals( $val ) {
// Split up each definiton
$direction = preg_split( $this->rspace, $val );
// 4 Direction reduction
$count = count( $direction );
if ( $count == 4 ) {
// All 4 sides are the same, combine into 1 definition
if ( $direction[ 0 ] == $direction[ 1 ] && $direction[ 2 ] == $direction[ 3 ] && $direction[ 0 ] == $direction[ 3 ] ) {
$direction = array( $direction[ 0 ] );
}
// top-bottom/left-right are the same, reduce definition
else if ( $direction[ 0 ] == $direction[ 2 ] && $direction[ 1 ] == $direction[ 3 ] ) {
$direction = array( $direction[ 0 ], $direction[ 1 ] );
}
// Only left-right are the same
else if ( $direction[ 1 ] == $direction[ 3 ] ) {
$direction = array( $direction[ 0 ], $direction[ 1 ], $direction[ 2 ] );
}
}
// 3 Direction reduction
else if ( $count == 3 ) {
// All directions are the same
if ( $direction[ 0 ] == $direction[ 1 ] && $direction[ 1 ] == $direction[ 2 ] ) {
$direction = array( $direction[ 0 ] );
}
// Only top(first) and bottom(last) are the same
else if ( $direction[ 0 ] == $direction[ 2 ] ) {
$direction = array( $direction[ 0 ], $direction[ 1 ] );
}
}
// 2 Direction reduction
// Both directions are the same, combine into single definition
else if ( $count == 2 && $direction[ 0 ] == $direction[ 1 ] ) {
$direction = array( $direction[ 0 ] );
}
// Return the combined version of the directions
// Single entries will just return
return implode( ' ', $direction );
}
/**
* Converts font-weight names to numbers
*
* @param (string) val: font-weight prop value
*/
private function fontweight( $val ) {
if ( preg_match( $this->rspace, $val ) ) {
$parts = preg_split( $this->rspace, $val );
foreach ( $parts as &$item ) {
$lower = strtolower( $item );
if ( isset( $this->weights[ $lower ] ) && $lower != 'normal' ) {
$item = $this->weights[ $lower ];
}
}
$val = implode( ' ', $parts );
}
else if ( isset( $this->weights[ strtolower( $val ) ] ) ) {
$val = $this->weights[ strtolower( $val ) ];
}
return $val;
}
/**
* Special font conversions
*
* @param (string) val: property value
*/
private function font( $val ) {
// Split out the font-size/line-height split and run through numerical handlers
if ( preg_match( $this->rsplitter, $val, $match, PREG_OFFSET_CAPTURE ) ) {
$size = $this->Numeric->numeric( $match[ 2 ][ 0 ] );
$height = $this->Numeric->numeric( $match[ 3 ][ 0 ] );
$concat = $match[ 1 ][ 0 ] . $size . '/' . $height . $match[ 4 ][ 0 ];
$val = substr_replace( $val, $concat, $match[ 0 ][ 1 ], strlen( $match[ 0 ][ 0 ] ) );
}
return $val;
}
/**
* Special clip conversions
*
* @param (string) val: property value
*/
private function clip( $val ) {
if ( preg_match( $this->rclip, $val, $match ) ) {
$positions = array( 1, 3, 5, 7 );
$clean = 'rect(';
foreach ( $positions as $pos ) {
if ( ! isset( $match[ $pos ] ) ) {
return $val;
}
$clean .= $this->Numeric->numeric( $match[ $pos ] ) . ( isset( $match[ $pos + 1 ] ) ? $match[ $pos + 1 ] : '' );
}
$val = $clean . ')';
}
return $val;
}
/**
* Convert none vals to 0
*
* @param (string) prop: Current Property
* @param (string) val: property value
*/
private function none( $prop, $val ) {
if ( preg_match( $this->rnoneprop, $prop ) && $val == 'none' ) {
$val = '0';
}
return $val;
}
/**
* MSIE Filter Conversion
*
* @param (string) prop: Current Property
* @param (string) val: property value
*/
private function filter( $prop, $val ) {
if ( preg_match( "/filter/", $prop ) ) {
$val = preg_replace( $this->rfilter, "alpha(opacity=$1)", $val );
}
return $val;
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $args );
}
else {
throw new CSSCompression_Exception( "Unknown method in Individuals Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,103 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Numeric
{
/**
* Numeric Patterns
*
* @class Control: Compression Controller
* @param (array) options: Reference to options
* @param (regex) rdecimal: Checks for zero decimal
* @param (regex) rzero: Checks for preceding 0 to decimal unit
* @param (regex) runit: Checks for suffix on 0 unit
*/
private $Control;
private $options = array();
private $rdecimal = "/^(\+|\-)?(\d*\.[1-9]*0*)(\%|[a-z]{2})$/i";
private $rzero = "/^(\+|\-)?0(\.\d+)(\%|[a-z]{2})?$/i";
private $runit = "/^0(\%|[a-z]{2})$/i";
/**
* Stash a reference to the controller on each instantiation
*
* @param (class) control: CSSCompression Controller
*/
public function __construct( CSSCompression_Control $control ) {
$this->Control = $control;
$this->options = &$control->Option->options;
}
/**
* Runs all numeric operations
*
* @param (string) str: Unit string
*/
public function numeric( $str ) {
$str = $this->decimal( $str );
$str = $this->zeroes( $str );
$str = $this->units( $str );
return $str;
}
/**
* Remove's unecessary decimal, ie 13.0px => 13px
*
* @param (string) str: Unit string
*/
private function decimal( $str ) {
if ( preg_match( $this->rdecimal, $str, $match ) ) {
$str = ( $match[ 1 ] == '-' ? '-' : '' ) . floatval( $match[ 2 ] ) . $match[ 3 ];
}
return $str;
}
/**
* Removes suffix from 0 unit, ie 0px; => 0;
*
* @param (string) str: Unit string
*/
private function units( $str ) {
if ( preg_match( $this->runit, $str, $match ) ) {
$str = '0';
}
return $str;
}
/**
* Removes leading zero in decimal, ie 0.33px => .33px
*
* @param (string) str: Unit string
*/
private function zeroes( $str ) {
if ( preg_match( $this->rzero, $str, $match ) ) {
$str = ( isset( $match[ 1 ] ) && $match[ 1 ] == '-' ? '-' : '' ) . $match[ 2 ] . ( isset( $match[ 3 ] ) ? $match[ 3 ] : '' );
}
return $str;
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $args );
}
else {
throw new CSSCompression_Exception( "Unknown method in Numeric Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,133 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Option
{
/**
* Option Patterns
*
* @class Control: Compression Controller
* @param (string) custom: Name of the custom mode
* @param (array) options: Instance settings
*/
private $Control;
private $custom = '__custom';
public $options = array();
/**
* Stash a reference to the controller on each instantiation
*
* @param (class) control: CSSCompression Controller
*/
public function __construct( CSSCompression_Control $control ) {
$this->Control = $control;
$this->options = CSSCompression::$defaults;
$control->mode = $this->custom;
}
/**
* Maintainable access to the options array
*
* - Passing no arguments returns the entire options array
* - Passing a single name argument returns the value for the option
* - Passing both a name and value, sets the value to the name key, and returns the value
* - Passing an array will merge the options with the array passed, for object like extension
*
* @param (mixed) name: The key name of the option
* @param (mixed) value: Value to set the option
*/
public function option( $name = NULL, $value = NULL ) {
if ( $name === NULL ) {
return $this->options;
}
else if ( is_array( $name ) ) {
return $this->merge( $name );
}
else if ( $value === NULL ) {
return isset( $this->options[ $name ] ) ? $this->options[ $name ] : NULL;
}
else {
// Readability doesn't signify custom settings
if ( $name != 'readability' ) {
$this->Control->mode = $this->custom;
}
return ( $this->options[ $name ] = $value );
}
}
/**
* Reset's the default options
*
* @params none;
*/
public function reset(){
// Reset and return the new options
return $this->options = CSSCompression::$defaults;
}
/**
* Extend like function to merge an array of preferences into
* the options array.
*
* @param (mixed) options: Array of preferences to merge into options
*/
public function merge( $options = array() ) {
$modes = CSSCompression::modes();
if ( $options && is_array( $options ) && count( $options ) ) {
$this->Control->mode = $this->custom;
foreach ( $this->options as $key => $value ) {
if ( ! isset( $options[ $key ] ) ) {
continue;
}
else if ( strtolower( $options[ $key ] ) == 'on' ) {
$this->options[ $key ] = true;
}
else if ( strtolower( $options[ $key ] ) == 'off' ) {
$this->options[ $key ] = false;
}
else {
$this->options[ $key ] = intval( $options[ $key ] );
}
}
}
else if ( $options && is_string( $options ) && array_key_exists( $options, $modes ) ) {
$this->Control->mode = $options;
// Default all to true, the mode has to force false
foreach ( $this->options as $key => $value ) {
if ( $key != 'readability' ) {
$this->options[ $key ] = true;
}
}
// Merge mode into options
foreach ( $modes[ $options ] as $key => $value ) {
$this->options[ $key ] = $value;
}
}
return $this->options;
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $args );
}
else {
throw new CSSCompression_Exception( "Unknown method in Option Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,149 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Organize
{
/**
* Organize Patterns
*
* @class Control: Compression Controller
* @param (array) options: Reference to options
* @param (regex) rsemicolon: Checks for semicolon without an escape '\' character before it
* @param (regex) rlastsemi: Checks for semicolon at the end of the string
*/
private $Control;
private $options = array();
private $rsemicolon = "/(?<!\\\);/";
private $rlastsemi = "/(?<!\\\);$/";
/**
* Stash a reference to the controller on each instantiation
*
* @param (class) control: CSSCompression Controller
*/
public function __construct( CSSCompression_Control $control ) {
$this->Control = $control;
$this->options = &$control->Option->options;
}
/**
* Look to see if we can combine selectors to reduce the number
* of definitions.
*
* @param (array) selectors: Array of selectors, map directly to details
* @param (array) details: Array of rule sets, map directly to selectors
*/
public function organize( &$selectors = array(), &$details = array() ) {
// Combining defns based on similar selectors
list ( $selectors, $details ) = $this->reduceSelectors( $selectors, $details );
// Combining defns based on similar details
list ( $selectors, $details ) = $this->reduceDetails( $selectors, $details );
// Return in package form
return array( $selectors, $details );
}
/**
* Combines multiply defined selectors by merging the rule sets,
* latter declarations overide declaratins at top of file
*
* @param (array) selectors: Array of selectors broken down by setup
* @param (array) details: Array of rule sets broken down by setup
*/
private function reduceSelectors( $selectors, $details ) {
$keys = array_keys( $selectors );
$max = array_pop( $keys ) + 1;
for ( $i = 0; $i < $max; $i++ ) {
if ( ! isset( $selectors[ $i ] ) ) {
continue;
}
for ( $k = $i + 1; $k < $max; $k++ ) {
if ( ! isset( $selectors[ $k ] ) ) {
continue;
}
if ( $selectors[ $i ] == $selectors[ $k ] ) {
// Prevent noticies
if ( ! isset( $details[ $i ] ) ) {
$details[ $i ] = '';
}
if ( ! isset( $details[ $k ] ) ) {
$details[ $k ] = '';
}
// We kill the last semicolon before organization, so account for that.
if ( $details[ $i ] != '' && $details[ $k ] != '' && ! preg_match( $this->rlastsemi, $details[ $i ] ) ) {
$details[ $i ] .= ';' . $details[ $k ];
}
else {
$details[ $i ] .= $details[ $k ];
}
// Remove the second part
unset( $selectors[ $k ], $details[ $k ] );
}
}
}
return array( $selectors, $details );
}
/**
* Combines multiply defined rule sets by merging the selectors
* in comma seperated format
*
* @param (array) selectors: Array of selectors broken down by setup
* @param (array) details: Array of rule sets broken down by setup
*/
private function reduceDetails( $selectors, $details ) {
$keys = array_keys( $selectors );
$max = array_pop( $keys ) + 1;
for ( $i = 0; $i < $max; $i++ ) {
if ( ! isset( $selectors[ $i ] ) ) {
continue;
}
$arr = preg_split( $this->rsemicolon, isset( $details[ $i ] ) ? $details[ $i ] : '' );
for ( $k = $i + 1; $k < $max; $k++ ) {
if ( ! isset( $selectors[ $k ] ) ) {
continue;
}
$match = preg_split( $this->rsemicolon, isset( $details[ $k ] ) ? $details[ $k ] : '' );
$x = array_diff( $arr, $match );
$y = array_diff( $match, $arr );
if ( count( $x ) < 1 && count( $y ) < 1 ) {
$selectors[ $i ] .= ',' . $selectors[ $k ];
unset( $details[ $k ], $selectors[ $k ] );
}
}
}
return array( $selectors, $details );
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $args );
}
else {
throw new CSSCompression_Exception( "Unknown method in Organize Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,245 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Selectors
{
/**
* Selector patterns
*
* @class Control: Compression Controller
* @param (string) token: Copy of the injection token
* @param (regex) ridattr: ID Attribute matcher (combined with token)
* @param (regex) rclassattr: class Attribute matcher (combined with token)
* @param (array) options: Reference to options
* @param (regex) rmark: Stop points during selector parsing
* @param (regex) ridclassend: End of a id/class string
* @param (regex) rescapedspace: for replacement in class attributes
* @param (regex) rquote: Checks for the next quote character
* @param (regex) rcomma: looks for an unescaped comma character
* @param (regex) rspace: looks for an unescaped space character
* @param (regex) rid: looks for an unescaped hash character
* @param (regex) rpseudo: Add space after first-letter|line pseudo selector
* --- when it occurs before comma or rule set
*/
private $Control;
private $token = '';
private $ridattr = "";
private $rclassattr = "";
private $options = array();
private $rmark = "/(?<!\\\)(#|\.|=)/";
private $ridclassend = "/(?<!\\\)[:#>~\[\+\*\. ]/";
private $rquote = "/(?<!\\\)(\"|')?\]/";
private $rescapedspace = "/\\\ /";
private $rcomma = "/(?<!\\\),/";
private $rspace = "/(?<!\\\)\s/";
private $rid = "/(?<!\\\)#/";
private $rpseudo = "/:first-(letter|line)(,|$)/i";
/**
* Stash a reference to the controller on each instantiation
*
* @param (class) control: CSSCompression Controller
*/
public function __construct( CSSCompression_Control $control ) {
$this->Control = $control;
$this->token = CSSCompression::TOKEN;
$this->ridattr = "/\[id=$this->token(.*?)$this->token\]/";
$this->rclassattr = "/\[class=$this->token(.*?)$this->token\]/";
$this->options = &$control->Option->options;
}
/**
* Selector specific optimizations
*
* @param (array) selectors: Array of selectors
*/
public function selectors( &$selectors = array() ) {
foreach ( $selectors as &$selector ) {
// Auto ignore sections
if ( strpos( $selector, $this->token ) === 0 ) {
continue;
}
// Smart casing and token injection
$selector = $this->parse( $selector );
// Converting attr to shorthanded selectors
if ( $this->options['attr2selector'] ) {
// Use id hash instead of id attr
$selector = $this->idAttribute( $selector );
// Use class notation instead of class attr
$selector = $this->classAttribute( $selector );
}
// Remove everything before final id in a selector
if ( $this->options['strict-id'] ) {
$selector = $this->strictid( $selector );
}
// Get rid of possible repeated selectors
$selector = $this->repeats( $selector );
// Add space after pseudo selectors (so ie6 doesn't complain)
if ( $this->options['pseudo-space'] ) {
$selector = $this->pseudoSpace( $selector );
}
}
return $selectors;
}
/**
* Converts selectors like BODY => body, DIV => div
* and injects tokens wrappers for attribute values
*
* @param (string) selector: CSS Selector
*/
private function parse( $selector ) {
$clean = '';
$substr = '';
$pos = 0;
while ( preg_match( $this->rmark, $selector, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$substr = substr( $selector, $pos, $match[ 0 ][ 1 ] + 1 - $pos );
$clean .= $this->options['lowercase-selectors'] ? strtolower( $substr ) : $substr;
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 1 ][ 0 ] );
// Class or id match
if ( $match[ 1 ][ 0 ] == '#' || $match[ 1 ][ 0 ] == '.' ) {
if ( preg_match( $this->ridclassend, $selector, $m, PREG_OFFSET_CAPTURE, $pos ) ) {
$clean .= substr( $selector, $pos, $m[ 0 ][ 1 ] - $pos );
$pos = $m[ 0 ][ 1 ];
}
else {
$clean .= substr( $selector, $pos );
$pos = strlen( $selector );
break;
}
}
// Start of a string
else if ( preg_match( $this->rquote, $selector, $m, PREG_OFFSET_CAPTURE, $pos ) ) {
if ( $selector[ $pos ] == "\"" || $selector[ $pos ] == "'" ) {
$pos++;
}
$clean .= $this->token . substr( $selector, $pos, $m[ 0 ][ 1 ] - $pos ) . $this->token . ']';
$pos = $m[ 0 ][ 1 ] + strlen( $m[ 0 ][ 0 ] );
}
// No break points left
else {
$clean .= substr( $selector, $pos );
$pos = strlen( $selector );
break;
}
}
return $clean . ( $this->options['lowercase-selectors'] ? strtolower( substr( $selector, $pos ) ) : substr( $selector, $pos ) );
}
/**
* Convert [id=blah] attribute selectors into id form selector (#blah)
*
* @param (string) selector: CSS Selector
*/
private function idAttribute( $selector ) {
$pos = 0;
while ( preg_match( $this->ridattr, $selector, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
// Don't convert if space found (not valid hash selector)
if ( strpos( $match[ 1 ][ 0 ], ' ' ) !== false ) {
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 0 ][ 0 ] );
continue;
}
$selector = substr_replace( $selector, '#' . $match[ 1 ][ 0 ], $match[ 0 ][ 1 ], strlen( $match[ 0 ][ 0 ] ) );
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 1 ][ 0 ] ) + 1;
}
return $selector;
}
/**
* Convert [class=blah] attribute selectors into class form selector (.blah)
*
* @param (string) selector: CSS Selector
*/
private function classAttribute( $selector ) {
$pos = 0;
while ( preg_match( $this->rclassattr, $selector, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
// Don't convert if prescense of dot separator found
if ( strpos( $match[ 1 ][ 0 ], '.' ) !== false ) {
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 0 ][ 0 ] );
continue;
}
$replace = '.' . preg_replace( $this->rescapedspace, ".", $match[ 1 ][ 0 ] );
$selector = substr_replace( $selector, $replace, $match[ 0 ][ 1 ], strlen( $match[ 0 ][ 0 ] ) );
$pos = $match[ 0 ][ 1 ] + strlen( $match[ 1 ][ 0 ] ) + 1;
}
return $selector;
}
/**
* Promotes nested id's to the front of the selector
*
* @param (string) selector: CSS Selector
*/
private function strictid( $selector ) {
$parts = preg_split( $this->rcomma, $selector );
foreach ( $parts as &$s ) {
if ( preg_match( $this->rid, $s ) ) {
$p = preg_split( $this->rid, $s );
$s = '#' . array_pop( $p );
}
}
return implode( ',', $parts );
}
/**
* Removes repeated selectors that have been comma separated
*
* @param (string) selector: CSS Selector
*/
private function repeats( $selector ) {
$parts = preg_split( $this->rcomma, $selector );
$parts = array_flip( $parts );
$parts = array_flip( $parts );
return implode( ',', $parts );
}
/**
* Adds space after pseudo selector for ie6 like a:first-child{ => a:first-child {
*
* @param (string) selector: CSS Selector
*/
private function pseudoSpace( $selector ) {
return preg_replace( $this->rpseudo, ":first-$1 $2", $selector );
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
if ( $method == 'selectors' ) {
return $this->selectors( $args[ 0 ] );
}
else {
return call_user_func_array( array( $this, $method ), $args );
}
}
else {
throw new CSSCompression_Exception( "Unknown method in Selectors Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,292 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Setup
{
/**
* Trim Patterns
*
* @class Control: Compression Controller
* @class Individuals: Individuals Instance
* @instance instance: CSSCompression Instance
* @param (string) token: Copy of the injection token
* @param (array) options: Reference to options
* @param (array) stats: Reference to stats
* @param (regex) rsemicolon: Checks for semicolon without an escape '\' character before it
* @param (regex) rcolon: Checks for colon without an escape '\' character before it
* @param (regex) rbang: Checks for '!' without an escape '\' character before it
* @param (regex) rspacebank: Checks for an unescaped space before a bang character
* @param (regex) rliner: Matching known 1-line intros
* @param (regex) rnested: Matching known subsection handlers
* @param (regex) rurl: url wrapper matching
* @param (regex) rsinglequote: Checks for unescaped escaped single quote (mouthfull)
* @param (array) rsetup: Expanding stylesheet for semi-tokenizing
*/
private $Control;
private $Individuals;
private $instance;
private $token = '';
private $options = array();
private $stats = array();
private $rsemicolon = "/(?<!\\\);/";
private $rcolon = "/(?<!\\\):/";
private $rbang = "/(?<!\\\)\!/";
private $rspacebang = "/(?<!\\\)\s\!/";
private $rliner = "/^@(import|charset|namespace)/i";
private $rmedia = "/^@media/i";
private $rurl = "/url\((.*?)\)/";
private $rsinglequote = "/(?<!\\\)\\\'/";
private $rsetup = array(
'patterns' => array(
"/(?<!\\\){/",
"/(?<!\\\)}/",
"/(?<!\\\)@/",
"/(@(charset|import)[^;]*(?<!\\\);)/",
),
'replacements' => array(
"\n{\n",
"\n}\n",
"\n@",
"$1\n",
),
);
/**
* Stash a reference to the controller on each instantiation
*
* @param (class) control: CSSCompression Controller
*/
public function __construct( CSSCompression_Control $control ) {
$this->Control = $control;
$this->Individuals = $control->Individuals;
$this->token = CSSCompression::TOKEN;
$this->options = &$control->Option->options;
$this->stats = &$control->stats;
}
/**
* Setup selector and details arrays for compression methods
*
* @param (string) css: Trimed stylesheet
*/
public function setup( $css ) {
// Seperate the element from the elements details
$css = explode( "\n", preg_replace( $this->rsetup['patterns'], $this->rsetup['replacements'], $css ) );
$newline = $this->options['readability'] > CSSCompression::READ_NONE ? "\n" : '';
$setup = array(
'selectors' => array(),
'details' => array(),
'unknown' => array(),
'introliner' => '',
'namespace' => '',
'import' => '',
'charset' => '',
);
while ( count( $css ) ) {
$row = trim( array_shift( $css ) );
if ( $row == '' ) {
continue;
}
// Single block At-Rule set
else if ( $row[ 0 ] == '@' && $css[ 0 ] == '{' && trim( $css[ 1 ] ) != '' && $css[ 2 ] == '}' ) {
// Stash selector
array_push( $setup['selectors'], $row );
// Stash details (after the opening brace)
array_push( $setup['details'], $this->details( trim( $css[ 1 ] ) ) );
// drop the details from the stack
$css = array_slice( $css, 3 );
}
// Single line At-Rules (import/charset/namespace)
else if ( preg_match( $this->rliner, $row, $match ) ) {
$setup[ $match[ 1 ] ] .= $this->liner( $row ) . $newline;
}
// Nested At-Rule declaration blocks
else if ( $row[ 0 ] == '@' && $css[ 0 ] == '{' ) {
// Stash atrule as selector
array_push( $setup['selectors'], $this->token . $row );
// Stash details (after the opening brace)
array_push( $setup['details'], $this->nested( $css, preg_match( $this->rmedia, $row ) ) . $newline );
}
// Unknown single line At-Rules
else if ( $row[ 0 ] == '@' && substr( $row, -1 ) == ';' ) {
$setup[ 'introliner' ] .= $row . $newline;
}
// Declaration Block
else if ( count( $css ) >= 3 && $css[ 0 ] == '{' && $css[ 2 ] == '}' ) {
// Stash selector
array_push( $setup['selectors'], $row );
// Stash details (after the opening brace)
array_push( $setup['details'], $this->details( trim( $css[ 1 ] ) ) );
// drop the details from the stack
$css = array_slice( $css, 3 );
}
// Last catch, store unknown artifacts as selectors with a token
// and give it an empty rule set
else {
// Still add to unknown stack, for notification
array_push( $setup['unknown'], $row );
// Stash unknown artifacts as selectors with a token
array_push( $setup['selectors'], $this->token . $row );
// Give it an empty rule set
array_push( $setup['details'], '' );
}
}
return $setup;
}
/**
* Run nested elements through a separate instance of compression
*
* @param (array) css: Reference to the original css array
* @param (bool) organize: Whether or not to organize the subsection (only true for media sections)
*/
private function nested( &$css = array(), $organize = false ) {
$options = $this->options;
$left = 0;
$right = 0;
$row = '';
$independent = '';
$content = '';
$spacing = '';
$newline = $this->options['readability'] > CSSCompression::READ_NONE ? "\n" : '';
// Find the end of the nested section
while ( count( $css ) && ( $left < 1 || $left > $right ) ) {
$row = trim( array_shift( $css ) );
if ( $row == '' ) {
continue;
}
else if ( $row == '{' ) {
$left++;
}
else if ( $row == '}' ) {
$right++;
}
else if ( count( $css ) && substr( $row, 0, 1 ) != '@' && substr( $css[ 0 ], 0, 1 ) == '@' && substr( $row, -1 ) == ';' ) {
$independent .= $row;
continue;
}
$content .= $row;
}
// Ensure copy of instance exists
if ( ! $this->instance ) {
$this->instance = new CSSCompression();
}
// Fresh start
$this->instance->reset();
// Compress the nested section independently after removing the wrapping braces
// Also make sure to only organize media sections
if ( $options['organize'] == true && $organize == false ) {
$options['organize'] = false;
}
// Independent sections should be prepended to the next compressed section
$content = ( $independent == '' ? '' : $independent . $newline )
. $this->instance->compress( substr( $content, 1, -1 ), $options );
// Formatting for anything higher then 0 readability
if ( $newline == "\n" ) {
$content = "\n\t" . str_replace( "\n", "\n\t", $content ) . "\n";
$spacing = $this->options['readability'] > CSSCompression::READ_MIN ? ' ' : '';
}
// Stash the compressed nested script
return "$spacing{" . $content . "}$newline";
}
/**
* Converts import/namespace urls into strings
*
* @param (string) row: At-rule
*/
private function liner( $row ) {
$pos = 0;
while ( preg_match( $this->rurl, $row, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
$quote = preg_match( $this->rsinglequote, $match[ 1 ][ 0 ] ) ? '"' : "'";
$replace = $quote . $match[ 1 ][ 0 ] . $quote;
$row = substr_replace( $row, $replace, $match[ 0 ][ 1 ], strlen( $match[ 0 ][ 0 ] ) );
$pos = $match[ 0 ][ 1 ] + strlen( $replace );
}
return $row;
}
/**
* Run individual compression techniques on each property of a selector
*
* @param (string) row: Selector properties
*/
private function details( $row ) {
$row = preg_split( $this->rsemicolon, $row );
$parts = array();
$details = '';
foreach ( $row as $line ) {
// Set loopers
$parts = preg_split( $this->rcolon, $line, 2 );
$prop = '';
$value = '';
// Property
if ( isset( $parts[ 0 ] ) && ( $parts[ 0 ] = trim( $parts[ 0 ] ) ) != '' ) {
$prop = $parts[ 0 ];
}
// Value
if ( isset( $parts[ 1 ] ) && ( $parts[ 1 ] = trim( $parts[ 1 ] ) ) != '' ) {
$value = preg_replace( $this->rbang, ' !', $parts[ 1 ] );
}
// Fail safe, remove unspecified property/values
if ( $prop == '' || $value == '' ) {
continue;
}
// Run the tag/element through each compression
list ( $prop, $value ) = $this->Individuals->individuals( $prop, $value );
// Add counter to before stats
$this->stats['before']['props']++;
// Store the compressed element
$details .= "$prop:" . preg_replace( $this->rspacebang, '!', $value ) . ";";
}
return $details;
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $args );
}
else {
throw new CSSCompression_Exception( "Unknown method in Setup Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,213 @@
<?php
/**
* CSS Compressor [VERSION]
* [DATE]
* Corey Hart @ http://www.codenothing.com
*/
Class CSSCompression_Trim
{
/**
* Trim Patterns
*
* @class Control: Compression Controller
* @param (array) options: Reference to options
* @param (regex) rcmark: Marking point when traversing through sheet for comments
* @param (regex) rendcomment: Finds the ending comment point
* @param (regex) rendquote: Finds the ending quote point
* @param (regex) rendsinglequote: Finds the ending single quote point
* @param (array) rescape: Array of patterns of groupings that should be escaped
* @param (array) trimmings: Stylesheet trimming patterns/replacements
* @param (array) escaped: Array of characters that need to be escaped
*/
private $Control;
private $options = array();
private $rcmark = "/((?<!\\\)\/\*|(?<!\\\)\"|(?<!\\\)')/";
private $rendcomment = "/\*\//";
private $rendquote = "/(?<!\\\)\"/";
private $rendsinglequote = "/(?<!\\\)'/";
private $rescape = array(
"/(url\()([^'\"].*?)(\))/is",
"/((?<!\\\)\")(.*?)((?<!\\\)\")/s",
"/((?<!\\\)')(.*?)((?<!\\\)')/s",
);
private $trimmings = array(
'patterns' => array(
"/(?<!\\\)(\s+)?(?<!\\\)([!,{};>\~\+\/])(?<!\\\)(\s+)?/s", // Remove un-needed spaces around special characters
"/url\((?<!\\\)\"(.*?)(?<!\\\)\"\)/is", // Remove quotes from urls
"/url\((?<!\\\)'(.*?)(?<!\\\)'\)/is", // Remove single quotes from urls
"/url\((.*?)\)/is", // Lowercase url wrapper
"/(?<!\\\);{2,}/", // Remove unecessary semi-colons
"/(?<!\\\)\s+/s", // Compress all spaces into single space
),
'replacements' => array(
'$2',
'url($1)',
'url($1)',
'url($1)',
';',
' ',
)
);
private $escaped = array(
'search' => array(
":",
";",
"}",
"{",
"@",
"!",
",",
">",
"+",
"~",
"/",
"*",
".",
"=",
"#",
"\r",
"\n",
"\t",
" ",
),
'replace' => array(
"\\:",
"\\;",
"\\}",
"\\{",
"\\@",
"\\!",
"\\,",
"\\>",
"\\+",
"\\~",
"\\/",
"\\*",
"\\.",
"\\=",
"\\#",
"\\r",
"\\n",
"\\t",
"\\ ",
),
);
/**
* Stash a reference to the controller on each instantiation
*
* @param (class) control: CSSCompression Controller
*/
public function __construct( CSSCompression_Control $control ) {
$this->Control = $control;
$this->options = &$control->Option->options;
}
/**
* Central trim handler
*
* @param (string) css: Stylesheet to trim
*/
public function trim( $css ) {
$css = $this->comments( $css );
$css = $this->escape( $css );
$css = $this->strip( $css );
return $css;
}
/**
* Does a quick run through the script to remove all comments from the sheet,
*
* @param (string) css: Stylesheet to trim
*/
private function comments( $css ) {
$pos = 0;
while ( preg_match( $this->rcmark, $css, $match, PREG_OFFSET_CAPTURE, $pos ) ) {
switch ( $match[ 1 ][ 0 ] ) {
// Start of comment block
case "/*":
if ( preg_match( $this->rendcomment, $css, $m, PREG_OFFSET_CAPTURE, $match[ 1 ][ 1 ] + 1 ) ) {
$end = $m[ 0 ][ 1 ] - $match[ 1 ][ 1 ] + strlen( $m[ 0 ][ 0 ] );
$css = substr_replace( $css, '', $match[ 1 ][ 1 ], $end );
$pos = $match[ 0 ][ 1 ];
}
else {
$css = substr( $css, 0, $match[ 1 ][ 1 ] );
break 2;
}
break;
// Start of string
case "\"":
if ( preg_match( $this->rendquote, $css, $m, PREG_OFFSET_CAPTURE, $match[ 1 ][ 1 ] + 1 ) ) {
$pos = $m[ 0 ][ 1 ] + strlen( $m[ 0 ][ 0 ] );
}
else {
break 2;
}
break;
// Start of string
case "'":
if ( preg_match( $this->rendsinglequote, $css, $m, PREG_OFFSET_CAPTURE, $match[ 1 ][ 1 ] + 1 ) ) {
$pos = $m[ 0 ][ 1 ] + strlen( $m[ 0 ][ 0 ] );
}
else {
break 2;
}
break;
// Should have never gotten here
default:
break 2;
}
}
return $css;
}
/**
* Escape out possible splitter characters within urls
*
* @param (string) css: Full stylesheet
*/
private function escape( $css ) {
foreach ( $this->rescape as $regex ) {
$start = 0;
while ( preg_match( $regex, $css, $match, PREG_OFFSET_CAPTURE, $start ) ) {
$value = $match[ 1 ][ 0 ]
. str_replace( $this->escaped['search'], $this->escaped['replace'], $match[ 2 ][ 0 ] )
. $match[ 3 ][ 0 ];
$css = substr_replace( $css, $value, $match[ 0 ][ 1 ], strlen( $match[ 0 ][ 0 ] ) );
$start = $match[ 0 ][ 1 ] + strlen( $value ) + 1;
}
}
return $css;
}
/**
* Runs initial formatting to setup for compression
*
* @param (string) css: CSS Contents
*/
private function strip( $css ) {
// Run replacements
return trim( preg_replace( $this->trimmings['patterns'], $this->trimmings['replacements'], $css ) );
}
/**
* Access to private methods for testing
*
* @param (string) method: Method to be called
* @param (array) args: Array of paramters to be passed in
*/
public function access( $method, $args ) {
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $args );
}
else {
throw new CSSCompression_Exception( "Unknown method in Trim Class - " . $method );
}
}
};
?>

View File

@@ -0,0 +1,21 @@
The MIT License
Copyright (c) 2011 Corey Hart
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.
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.

View File

@@ -1,2 +0,0 @@
[InternetShortcut]
URL=http://optipng.sourceforge.net/

View File

@@ -1,32 +0,0 @@
CAVEAT EMPTOR
=============
(known bugs, problems or limitations)
Legend
------
- Minor bug, limitation, or incompletely-implemented feature.
! Bug that may lead to a behavior different than expected,
but without any serious consequence.
!! Bug that may cause accidental data loss, security hazard,
or another serious consequence.
* Another problematic issue, that is not necessarily a bug.
Version 0.6.4 14-mar-2010
-------------
- Lossless image reductions are not completely implemented.
(This does NOT affect the integrity of PNG files.)
Here are the missing pieces:
- The color palette reductions are implemented only partially.
- The bit depth reductions below 8, for grayscale images, are
not implemented yet.
- TIFF support is limited to uncompressed, PNG-compatible
color spaces (grayscale, RGB and RGBA).
- Metadata is not imported from the external image formats.
- There is no support for pipes or streams.

View File

@@ -1,318 +0,0 @@
OptiPNG - Revision history
==========================
Legend
------
++ Added or improved performance-related feature
(might improve compression ratio or processing speed).
+ Added or improved feature.
- Removed feature.
! Fixed bug.
!! Fixed dangerous bug
(data/metadata loss or serious security hazard).
* Other modification (e.g. architectural improvement).
Version 0.6.4 14-mar-2010
-------------
+ Upgraded libpng to version 1.4.1-optipng [private]
+ Upgraded zlib to version 1.2.4-optipng [private]
+ Added the option -nx.
* Clarified the behavior of -nz and the relation between -nz and -o0.
+ Added a filesystem check (resolving normalized paths, symlinks, etc.)
to better detect when the output overwrites the input.
+ Enabled automatic wildcard expansion (i.e. globbing) on Win64.
! Fixed a Unicode build issue on Windows.
(Thanks to Fabien Barbier for the fix.)
Version 0.6.3 18-may-2009
-------------
+ Upgraded libpng to version 1.2.36-optipng [private]
!! Fixed a use-after-free error in the GIF reader.
(Thanks to Roy Tam for the report, and to Bryan McQuade for the fix.)
! Flushed the output log to display the current trial in real time.
This only worked on Windows in the previous version.
(Thanks to Vincent Lefevre for the fix.)
! Fixed an error in reporting unrecognized file formats.
(Thanks to [LaughingMan] for the report.)
- Removed the requirement to "fix" TIFF files that contain unrecognized
metadata. (Thanks to Piotr Bandurski for the suggestion.)
* Simplified the option abbreviation rules. Option names can now be
abbreviated to their shortest unique prefix, as in X11 applications.
Version 0.6.2 9-nov-2008
-------------
+ Upgraded libpng to version 1.2.33-optipng [private]
++ Put back a speed optimization, accidentally removed in version 0.6,
allowing singleton trials (-o1) to be bypassed in certain conditions.
!! Fixed an array overflow in the BMP reader.
!! Fixed the loss of private chunks under the -snip option.
+ Produced a more concise on-screen output in the non-verbose mode.
(Thanks to Vincent Lefevre for the contribution.)
* Added a programming interface to the optimization engine, in order
to facilitate the development of PNG-optimizing GUI apps and plugins.
Version 0.6.1 20-jul-2008
-------------
* Upgraded cexcept to version 2.0.1.
+ Added a configure script, to be used instead of unix-secure.mak.
! Fixed a build issue that occured when using libpng from the system.
(Thanks to Nelson A. de Oliveira for the report.)
! Fixed processing when image reduction yields an output larger than
the original. (Thanks to Michael Krishtopa for the report.)
! Fixed behavior of -preserve.
(Thanks to Bill Koch for the report.)
- Removed displaying of partial progress when abandoning IDATs under
the -v option. The percentages displayed were not very accurate.
Version 0.6 15-jun-2008
-----------
+ Upgraded libpng to version 1.2.29-optipng [private]
++ Implemented grayscale(alpha)-to-palette reductions.
++ Improved conversion of bKGD info during RGB-to-palette reductions.
(Thanks to Matthew Fearnley for the contribution.)
!! Fixed conversion of bKGD and tRNS during 16-to-8-bit reductions.
(Thanks to Matthew Fearnley for the report.)
+ Added support for compressed BMP (incl. PNG-compressed BMP, you bet!)
+ Improved the speed of reading raw PNM files.
+ Recognized PNG digital signatures (dSIG) and disabled optimization
in their presence, to preserve their integrity.
+ Allowed the user to enforce the optimization of dSIG'ed files.
+ Recognized APNG animation files and disabled reductions to preserve
their integrity.
+ Added the -snip option, to allow the user to "snip" one image out of
a multi-image file, such as animated GIF, multi-page TIFF, or APNG.
(Thanks to [LaughingMan] for the suggestion.)
+ Improved recovery of PNG files with incomplete IDAT.
!! Fixed a crash triggered by the use of -log on some platforms.
(Thanks to Stefan Bruns for the fix.)
! Fixed behavior of -out and -dir when the input is already optimized.
(Thanks to Christian Davideck for the report.)
* Provided more detailed image information at the start of processing.
* Provided a more detailed summary at the end of processing, under the
presence of the -v option and/or the occurence of exceptional events.
Version 0.5.5 28-jan-2007
-------------
+ Upgraded libpng to version 1.2.15-optipng [private]
++ Used a previously-missed RGB-to-palette reduction opportunity
for images containing 256 distinct colors.
(Thanks to Joachim Kluge for the report.)
!! Fixed conversion of bKGD info during RGB-to-palette reductions.
(Thanks to Matthew Fearnley for the report.)
! Fixed pre-computation of iterations.
(Thanks to Matthew Fearnley for the report.)
! Eliminated a false alarm when processing RGB images with tRNS
in Unix-secure mode. (Thanks to Till Maas for the report, and
thanks to Nelson A. de Oliveira for the fix.)
! Fixed behavior of -out and -dir when changing interlacing.
(Thanks to Martin Packman for the report.)
! Fixed the behavior of "-dir [DRIVE]:" on Windows.
Version 0.5.4 11-aug-2006
-------------
+ Added user options -out and -dir, to specify the name of
the output file or directory.
(Thanks to Alexander Lucas for the suggestion.)
* Added support for builds based on the system-supplied libpng.
(Thanks to Nelson A. de Oliveira for the valuable help.)
Version 0.5.3 23-jul-2006
-------------
+ Upgraded libpng to version 1.2.12-optipng [private]
+ Implemented basic support for TIFF (grayscale, RGB and RGBA,
uncompressed).
++ Avoided the redundant trial when the search space is singular
(e.g. when running "optipng -o1 example.tif").
+ Prevented accidental file corruption when using option "-log".
! Fixed (again) a small typo in the online help.
Version 0.5.2 7-may-2006
-------------
+ Improved handling of inexact PNM-to-PNG conversions.
! Fixed a typo that was breaking the build on some Unix platforms.
(Thanks to Aaron Reitz for the report.)
Version 0.5.1 30-apr-2006
-------------
++ Implemented bit depth reduction for palette images.
+ Upgraded libpng to version 1.2.10-optipng [private]
+ Improved the BMP support.
+ Added a Unix man page.
(Thanks to Nelson A. de Oliveira for the contribution.)
+ Allowed abbreviation of command-line options.
+ Changed user option -log to accept a file name as an argument.
* Changed user option -no to -simulate.
! Fixed an error in handling .bak files on Unix.
(Thanks to Adam Szojda and Nelson A. de Oliveira for the report.)
! Fixed a small typo in the help screen.
(Thanks to A. Costa and Nelson A. de Oliveira for the report.)
Version 0.5 14-jan-2006
-----------
++ Added pngxtern, a libpng add-on for external image format
support: BMP (uncompressed), GIF, PNM.
(This was incorporated from OptiPNG-Plus.)
++ Implemented RGB(A)-to-palette reductions.
+ Upgraded zlib to version 1.2.3-optipng [private]
+ Upgraded libpng to version 1.2.8-optipng [private]
+ If trials are ended prematurely, detailed progression is only
reported under the user option -v.
- Removed reporting of some IDAT sizes that exceeded the optimum.
(This was NOT a bug, but a "feature" that confused some users.)
! Fixed an RGB-to-gray reduction problem that occured under some
specific background colors.
* Added support for builds based on the system-supplied zlib.
(Thanks to Nelson A. de Oliveira for the suggestion.)
* Modified LICENSE. It is now a verbatim spell of the zlib license.
Version 0.4.8 10-may-2005
-------------
+ Upgraded libpng to version 1.0.18-optipng [private]
!! Fixed a palette-to-gray reduction problem that occurred when an
RGB triple had both an alpha below max, and an alpha equal to max.
(Thanks to Nicolas Le Gland for the report.)
+ Packed the Windows executable using UPX.
(Thanks to [Warriant] for the suggestion.)
Version 0.4.7 30-oct-2004
-------------
!! Fixed a palette-to-gray reduction problem that occurred when
having more than one alpha value per RGB triple.
(Thanks to Larry Hastings for the report.)
! Fixed the progress display, when processing very large images.
+ Displayed the image info at the beginning of processing.
++ Reduced the IDAT buffer size, allowing abandoned trials to
terminate earlier in some circumstances.
+ Implemented error recovery, when PLTE is too small, and/or
tRNS is too large.
Version 0.4.6 25-oct-2004
-------------
+ Upgraded zlib to version 1.2.2-optipng [private]
+ Upgraded libpng to version 1.0.17-optipng [private]
This provides safe handling of some ill-formed PNG images.
+ Rewrote makefiles.
+ Added project workspace to build under Visual C++ 6.0,
integrated with memory leak detection.
++ Implemented a premature termination of trials, in the moment
when IDAT grows beyond the smallest size previously achieved.
(Thanks to Larry Hastings for the idea.)
+ Changed the order of trials, to perform the trials that are
more likely to yield a smaller IDAT, at the beginning.
+ Added user option -full to avoid the premature termination of
trials; useful for debugging.
Version 0.4.5 31-may-2004
-------------
+ Upgraded zlib to version 1.2.1.f-cos2 [private]
+ Upgraded libpng to version 1.0.15-cos2 [private]
* Changed user option -nx to -nz.
+ Added user option to preserve file attributes (file mode,
time stamp, etc.) when applicable.
(Thanks to Nehal Mistry for the suggestion.)
! Fixed an incorrect initialization of zlib window bits.
! Displayed an error message when the search space was invalid.
!! Fixed a palette reduction problem for bit depths below 8.
! Eliminated memory leaks.
(Thanks to Niels de Koning for the help.)
Version 0.4.4 20-nov-2003
-------------
+ Upgraded zlib to version 1.2.1
++ Added support for the Z_RLE strategy.
Version 0.4.3 12-aug-2003
-------------
! Fixed a reduction problem that caused an assertion failure.
(Thanks to Dimitri Papadopoulos for the report.)
Version 0.4.2 30-jun-2003
-------------
++ Enhanced the support for palette size reductions:
trailing sterile palette entries are removed even when
the bit depth is below 8.
! Enforced recompression when the new IDAT has the same size,
but other chunks have been reduced.
+ Displayed the IDAT size difference as a percentage.
(Thanks to Nehal Mistry for the suggestion.)
Version 0.4.1 19-may-2003
-------------
! Fixed the removal of trailing sterile palette entries.
Version 0.4 12-may-2003
-----------
++ Added support for palette-to-gray reductions.
++ Added partial support for palette size reductions.
! Fixed the reporting of invalid command-line options.
! Eliminated a spurious warning when the zlib window size
is set to 256.
Version 0.3.2 11-mar-2003
-------------
+ Added support for updating sBIT during reductions.
! Fixed the reduction of the alpha channel.
Version 0.3.1 25-feb-2003
-------------
! Fixed the encoding of interlaced images when they become
larger than the input.
(Thanks to James H. Cloos, Jr. for the report.)
+ Added the HISTORY document (this file).
Version 0.3 24-feb-2003
-----------
This is the first public release of OptiPNG.
++ Added support for iterating through zlib memory levels.
++ Added support for collapsing IDAT, avoiding calls to
png_set_compression_buffer_size().
This reduces the memory requirements.
++ Added support for lossless reduction of the image type:
RGB[A] -> G[A], RGBA -> RGB, GA -> G
+ Added many user options.
+ Added documentation.
Version 0.2 27-dec-2001
-----------
+ Added support for optimization level presets.
+ Added user option for changing the interlacing.
Version 0.1 17-dec-2001
-----------
+ Added support for chunk I/O status annotation.
This improves the speed of OptiPNG significantly.
* Structured exception handling is provided by cexcept.
Version 0.0 10-dec-2001
-----------
This is the very first version of OptiPNG.
It compresses IDAT repeatedly, iterating through zlib compression
and strategy levels, and PNG filters.

View File

@@ -1,677 +0,0 @@
<!-- Creator : groff version 1.19.2 -->
<!-- CreationDate: Sun Mar 14 12:29:16 2010 -->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta name="generator" content="groff -Thtml, see www.gnu.org">
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<meta name="Content-Style" content="text/css">
<style type="text/css">
p { margin-top: 0; margin-bottom: 0; }
pre { margin-top: 0; margin-bottom: 0; }
table { margin-top: 0; margin-bottom: 0; }
</style>
<title>OPTIPNG</title>
</head>
<body>
<h1 align=center>OPTIPNG</h1>
<hr>
<a name="NAME"></a>
<h2>NAME</h2>
<p style="margin-left:11%; margin-top: 1em"><b>OptiPNG</b>
&minus; Advanced optimization program for <b>Portable
Network Graphics (PNG)</b></p>
<a name="SYNOPSIS"></a>
<h2>SYNOPSIS</h2>
<p style="margin-left:11%; margin-top: 1em"><b>optipng</b>
[<b>&minus;?</b> | <b>&minus;h</b> | <b>&minus;help</b>]
<b><br>
optipng</b> [<i>options...</i>] <i>files...</i></p>
<a name="DESCRIPTION"></a>
<h2>DESCRIPTION</h2>
<p style="margin-left:11%; margin-top: 1em">The
<b>OptiPNG</b> program shall attempt to <i>optimize</i> PNG
files, i.e. reduce their size to a minimum, without losing
any information. In addition, this program shall perform a
suite of auxiliary functions like integrity checks, metadata
recovery and pixmap-to-PNG conversion.</p>
<p style="margin-left:11%; margin-top: 1em">The
optimization attempts are not guaranteed to succeed. Valid
PNG files that cannot be optimized by this program are
normally left intact; their size will not grow. The user may
request to override this default behavior.</p>
<a name="FILES"></a>
<h2>FILES</h2>
<p style="margin-left:11%; margin-top: 1em">The input files
are raster image files encoded either in PNG format (the
native format), or in an external format. The currently
supported external formats are GIF, BMP, PNM and TIFF.</p>
<p style="margin-left:11%; margin-top: 1em"><b>OptiPNG</b>
processes each image file given in the command line as
follows:</p>
<p style="margin-left:11%; margin-top: 1em">&minus; If it
is in PNG format:</p>
<p style="margin-left:22%; margin-top: 1em">Attempt to
optimize the given file in-place. If optimization is
successful, or if the option <b>&minus;force</b> is in
effect, replace the original file with its optimized
version. The original file is backed up if the option
<b>&minus;keep</b> is in effect.</p>
<p style="margin-left:11%; margin-top: 1em">&minus; If it
is in an external format:</p>
<p style="margin-left:22%; margin-top: 1em">Create an
optimized PNG version of the given file. The output file
name is composed from the original file name and the
<tt>.png</tt> extension.</p>
<a name="OPTIONS"></a>
<h2>OPTIONS</h2>
<p style="margin-left:11%; margin-top: 1em"><b>General
options <br>
-?</b>, <b>&minus;h</b>, <b>&minus;help</b></p>
<p style="margin-left:22%;">Show a complete summary of
options.</p>
<p style="margin-left:11%;"><b>&minus;o</b>
<i>level</i></p>
<p style="margin-left:22%;">Select the optimization level.
<br>
The optimization level 0 enables a set of optimization
operations that require minimal effort. There will be no
changes to image attributes like bit depth or color type,
and no recompression of existing IDAT datastreams. <br>
The optimization level 1 enables a single IDAT compression
trial. The trial chosen is what <b>OptiPNG</b> <i>thinks</i>
it&rsquo;s probably the most effective. <br>
The optimization levels 2 and higher enable multiple IDAT
compression trials; the higher the level, the more trials.
<br>
The behavior and the default value of this option may change
across different program versions. Use the option
<b>&minus;h</b> to see the details pertaining to your
specific version.</p>
<p style="margin-left:11%;"><b>&minus;dir</b>
<i>directory</i></p>
<p style="margin-left:22%;">Write output file(s) to
<i>directory</i>.</p>
<table width="100%" border=0 rules="none" frame="void"
cellspacing="0" cellpadding="0">
<tr valign="top" align="left">
<td width="11%"></td>
<td width="6%">
<p style="margin-top: 1em" valign="top"><b>&minus;fix</b></p> </td>
<td width="5%"></td>
<td width="78%">
<p style="margin-top: 1em" valign="top">Enable error
recovery. This option has no effect on valid input
files.</p> </td>
</table>
<p style="margin-left:22%;">The program will spend a
reasonable amount of effort to recover as much data as
possible, without increasing the output file size, but the
success cannot be generally guaranteed. The program may even
increase the file size, e.g., by reconstructing missing
critical data. Under this option, integrity shall take
precedence over file size. <br>
When this option is not used, the invalid input files are
left unprocessed.</p>
<table width="100%" border=0 rules="none" frame="void"
cellspacing="0" cellpadding="0">
<tr valign="top" align="left">
<td width="11%"></td>
<td width="9%">
<p style="margin-top: 1em" valign="top"><b>&minus;force</b></p> </td>
<td width="2%"></td>
<td width="56%">
<p style="margin-top: 1em" valign="top">Enforce writing of
a new output file.</p></td>
<td width="22%">
</td>
</table>
<p style="margin-left:22%;">This option overrides the
program&rsquo;s decision not to write such file, e.g. when
the PNG input is digitally signed (using dSIG), or when the
PNG output becomes larger than the PNG input.</p>
<table width="100%" border=0 rules="none" frame="void"
cellspacing="0" cellpadding="0">
<tr valign="top" align="left">
<td width="11%"></td>
<td width="7%">
<p style="margin-top: 1em" valign="top"><b>&minus;keep</b></p> </td>
<td width="4%"></td>
<td width="58%">
<p style="margin-top: 1em" valign="top">Keep a backup of
the modified file(s).</p></td>
<td width="20%">
</td>
</table>
<p style="margin-left:22%;">The files that use the backup
names prior to the program execution are <i>not</i>
overwritten.</p>
<p style="margin-left:11%;"><b>&minus;log</b>
<i>file</i></p>
<p style="margin-left:22%;">Log messages to <i>file</i>.
For safety reasons, <i>file</i> must have the extension
<tt>.log</tt>.</p>
<p style="margin-left:11%;"><b>&minus;out</b>
<i>file</i></p>
<p style="margin-left:22%;">Write output file to
<i>file</i>. The command line must contain exactly one input
file.</p>
<p style="margin-left:11%;"><b>&minus;preserve</b></p>
<p style="margin-left:22%;">Preserve file attributes (time
stamps, file access rights, etc.) where applicable.</p>
<table width="100%" border=0 rules="none" frame="void"
cellspacing="0" cellpadding="0">
<tr valign="top" align="left">
<td width="11%"></td>
<td width="9%">
<p style="margin-top: 1em" valign="top"><b>&minus;quiet</b></p> </td>
<td width="2%"></td>
<td width="27%">
<p style="margin-top: 1em" valign="top">Run in quiet
mode.</p> </td>
<td width="51%">
</td>
</table>
<p style="margin-left:22%;">These messages are still
written to the log file if the option <b>&minus;log</b> is
in effect.</p>
<p style="margin-left:11%;"><b>&minus;simulate</b></p>
<p style="margin-left:22%;">Run in simulation mode: perform
the trials, but do not create output files.</p>
<table width="100%" border=0 rules="none" frame="void"
cellspacing="0" cellpadding="0">
<tr valign="top" align="left">
<td width="11%"></td>
<td width="7%">
<p style="margin-top: 1em" valign="top"><b>&minus;snip</b></p> </td>
<td width="4%"></td>
<td width="78%">
<p style="margin-top: 1em" valign="top">Cut one image out
of multi-image, animation or video file(s).</p></td>
</table>
<p style="margin-left:22%;">Depending on the input format,
this may be either the first or the most relevant (e.g. the
largest) image.</p>
<table width="100%" border=0 rules="none" frame="void"
cellspacing="0" cellpadding="0">
<tr valign="top" align="left">
<td width="11%"></td>
<td width="3%">
<p style="margin-top: 1em" valign="top"><b>&minus;v</b></p> </td>
<td width="8%"></td>
<td width="63%">
<p style="margin-top: 1em" valign="top">Enable the options
<b>&minus;verbose</b> and <b>&minus;version</b>.</p></td>
<td width="15%">
</td>
</table>
<p style="margin-left:11%;"><b>&minus;verbose</b></p>
<p style="margin-left:22%;">Run in verbose mode.</p>
<p style="margin-left:11%;"><b>&minus;version</b></p>
<p style="margin-left:22%;">Show copyright, version and
build info.</p>
<table width="100%" border=0 rules="none" frame="void"
cellspacing="0" cellpadding="0">
<tr valign="top" align="left">
<td width="11%"></td>
<td width="3%">
<p style="margin-top: 1em" valign="top"><b>&minus;&minus;</b></p> </td>
<td width="8%"></td>
<td width="41%">
<p style="margin-top: 1em" valign="top">Stop option switch
parsing.</p> </td>
<td width="37%">
</td>
</table>
<p style="margin-left:11%; margin-top: 1em"><b>PNG encoding
and optimization options <br>
&minus;f</b> <i>filters</i></p>
<p style="margin-left:22%;">Select the PNG delta filters.
<br>
The <i>filters</i> argument is specified as a rangeset (e.g.
<b>&minus;f0&minus;5</b>), and the default <i>filters</i>
value depends on the optimization level set by the option
<b>&minus;o</b>. <br>
The filter values 0, 1, 2, 3 and 4 indicate static
filtering, and correspond to the standard PNG filter codes
(<i>None</i>, <i>Left</i>, <i>Up</i>, <i>Average</i> and
<i>Paeth</i>, respectively). The filter value 5 indicates
adaptive filtering, whose effect is defined by the
<b>libpng</b>(3) library used by <b>OptiPNG</b>.</p>
<table width="100%" border=0 rules="none" frame="void"
cellspacing="0" cellpadding="0">
<tr valign="top" align="left">
<td width="11%"></td>
<td width="7%">
<p style="margin-top: 1em" valign="top"><b>&minus;full</b></p> </td>
<td width="4%"></td>
<td width="78%">
<p style="margin-top: 1em" valign="top">Produce a full
report on IDAT. This option might slow down the trials.</p></td>
</table>
<p style="margin-left:11%;"><b>&minus;i</b> <i>type</i></p>
<p style="margin-left:22%;">Select the interlace type
(0&minus;1). <br>
If the interlace type 0 is selected, the output image shall
be non-interlaced (i.e. progressive-scanned). If the
interlace type 1 is selected, the output image shall be
interlaced using the <i>Adam7</i> method. <br>
By default, the output shall have the same interlace type as
the input.</p>
<table width="100%" border=0 rules="none" frame="void"
cellspacing="0" cellpadding="0">
<tr valign="top" align="left">
<td width="11%"></td>
<td width="4%">
<p style="margin-top: 1em" valign="top"><b>&minus;nb</b></p> </td>
<td width="7%"></td>
<td width="78%">
<p style="margin-top: 1em" valign="top">Do not apply bit
depth reduction.</p></td>
<tr valign="top" align="left">
<td width="11%"></td>
<td width="4%">
<p style="margin-top: 1em" valign="top"><b>&minus;nc</b></p> </td>
<td width="7%"></td>
<td width="78%">
<p style="margin-top: 1em" valign="top">Do not apply color
type reduction.</p></td>
<tr valign="top" align="left">
<td width="11%"></td>
<td width="4%">
<p style="margin-top: 1em" valign="top"><b>&minus;np</b></p> </td>
<td width="7%"></td>
<td width="78%">
<p style="margin-top: 1em" valign="top">Do not apply
palette reduction.</p></td>
<tr valign="top" align="left">
<td width="11%"></td>
<td width="4%">
<p style="margin-top: 1em" valign="top"><b>&minus;nx</b></p> </td>
<td width="7%"></td>
<td width="78%">
<p style="margin-top: 1em" valign="top">Do not apply any
lossless image reduction: enable the options
<b>&minus;nb</b>, <b>&minus;nc</b> and <b>&minus;np</b>.</p></td>
<tr valign="top" align="left">
<td width="11%"></td>
<td width="4%">
<p style="margin-top: 1em" valign="top"><b>&minus;nz</b></p> </td>
<td width="7%"></td>
<td width="78%">
<p style="margin-top: 1em" valign="top">Do not recode IDAT
datastreams.</p> </td>
</table>
<p style="margin-left:22%;">The IDAT optimization
operations that do not require recoding (e.g. IDAT chunk
concatenation) are still performed. <br>
This option has effect on PNG input files only.</p>
<p style="margin-left:11%;"><b>&minus;zc</b>
<i>levels</i></p>
<p style="margin-left:22%;">Select the zlib compression
levels used in IDAT compression. <br>
The <i>levels</i> argument is specified as a rangeset (e.g.
<b>&minus;zc6&minus;9</b>), and the default <i>levels</i>
value depends on the optimization level set by the option
<b>&minus;o</b>. <br>
The effect of this option is defined by the <b>zlib</b>(3)
library used by <b>OptiPNG</b>.</p>
<p style="margin-left:11%;"><b>&minus;zm</b>
<i>levels</i></p>
<p style="margin-left:22%;">Select the zlib memory levels
used in IDAT compression. <br>
The <i>levels</i> argument is specified as a rangeset (e.g.
<b>-zm8&minus;9</b>), and the default <i>levels</i> value
depends on the optimization level set by the option
<b>&minus;o</b>. <br>
The effect of this option is defined by the <b>zlib</b>(3)
library used by <b>OptiPNG</b>.</p>
<p style="margin-left:11%;"><b>&minus;zs</b>
<i>strategies</i></p>
<p style="margin-left:22%;">Select the zlib compression
strategies used in IDAT compression. <br>
The <i>strategies</i> argument is specified as a rangeset
(e.g. <b>-zs0&minus;3</b>), and the default
<i>strategies</i> value depends on the optimization level
set by the option <b>&minus;o</b>. <br>
The effect of this option is defined by the <b>zlib</b>(3)
library used by <b>OptiPNG</b>.</p>
<p style="margin-left:11%;"><b>&minus;zw</b>
<i>size</i></p>
<p style="margin-left:22%;">Select the zlib window size
(32k,16k,8k,4k,2k,1k,512,256) used in IDAT compression. <br>
The <i>size</i> argument can be specified either in bytes
(e.g. 16384) or kilobytes (e.g. 16k). The default
<i>size</i> value is set to the lowest window size that
yields an IDAT output as big as if yielded by the value
32768. <br>
The effect of this option is defined by the <b>zlib</b>(3)
library used by <b>OptiPNG</b>.</p>
<p style="margin-left:11%; margin-top: 1em"><b>Notes</b>
<br>
Options may come in any order (except for
<b>&minus;&minus;</b>), before, after, or alternating with
file names. Option names are case-insensitive and may be
abbreviated to their shortest unique prefix.</p>
<p style="margin-left:11%; margin-top: 1em">Some options
may have arguments that follow the option name, separated by
whitespace or the equal sign (&rsquo;<b>=</b>&rsquo;). If
the option argument is a number or a rangeset, the separator
may be omitted. For example:</p>
<p style="margin-left:22%; margin-top: 1em"><b>&minus;out</b>
<tt>newfile.png</tt> &lt;=&gt;
<b>&minus;out=</b><tt>newfile.png</tt> <b><br>
&minus;o3</b> &lt;=&gt; <b>&minus;o&nbsp;3</b> &lt;=&gt;
<b>&minus;o=3 <br>
&minus;f0,3&minus;5</b> &lt;=&gt;
<b>&minus;f&nbsp;0,3&minus;5</b> &lt;=&gt;
<b>&minus;f=0,3&minus;5</b></p>
<p style="margin-left:11%; margin-top: 1em">Rangeset
arguments are cumulative; e.g.</p>
<p style="margin-left:22%; margin-top: 1em"><b>&minus;f0
&minus;f3&minus;5</b> &lt;=&gt; <b>&minus;f0,3&minus;5 <br>
&minus;zs0 &minus;zs1 &minus;zs2&minus;3</b> &lt;=&gt;
<b>&minus;zs0,1,2,3</b> &lt;=&gt;
<b>&minus;zs0&minus;3</b></p>
<a name="EXTENDED DESCRIPTION"></a>
<h2>EXTENDED DESCRIPTION</h2>
<p style="margin-left:11%; margin-top: 1em">The PNG
optimization algorithm consists of the following steps:</p>
<table width="100%" border=0 rules="none" frame="void"
cellspacing="0" cellpadding="0">
<tr valign="top" align="left">
<td width="11%"></td>
<td width="3%">
<p style="margin-top: 1em" valign="top">1.</p></td>
<td width="3%"></td>
<td width="83%">
<p style="margin-top: 1em" valign="top">Reduce the bit
depth, the color type and the color palette of the image.
This step may reduce the size of the uncompressed image,
which, indirectly, may reduce the size of the compressed
image (i.e. the size of the output PNG file).</p></td>
<tr valign="top" align="left">
<td width="11%"></td>
<td width="3%">
<p style="margin-top: 1em" valign="top">2.</p></td>
<td width="3%"></td>
<td width="83%">
<p style="margin-top: 1em" valign="top">Run a suite of
compression methods and strategies and select the
compression parameters that yield the smallest output
file.</p> </td>
<tr valign="top" align="left">
<td width="11%"></td>
<td width="3%">
<p style="margin-top: 1em" valign="top">3.</p></td>
<td width="3%"></td>
<td width="83%">
<p style="margin-top: 1em" valign="top">Store all IDAT
contents into a single chunk, eliminating the overhead
incurred by repeated IDAT headers and CRCs.</p></td>
<tr valign="top" align="left">
<td width="11%"></td>
<td width="3%">
<p style="margin-top: 1em" valign="top">4.</p></td>
<td width="3%"></td>
<td width="83%">
<p style="margin-top: 1em" valign="top">Set the zlib window
size inside IDAT to a mininum that does not affect the
compression ratio, reducing the memory requirements of PNG
decoders.</p> </td>
</table>
<p style="margin-left:11%; margin-top: 1em">Not all of the
above steps need to be executed. The behavior depends on the
actual input files and user options.</p>
<p style="margin-left:11%; margin-top: 1em">Step 1 may be
customized via the no-reduce options <b>&minus;nb</b>,
<b>&minus;nc</b>, <b>&minus;np</b> and <b>&minus;nx</b>.
Step 2 may be customized via the <b>&minus;o</b> option, and
may be fine-tuned via the options <b>&minus;zc</b>,
<b>&minus;zm</b>, <b>&minus;zs</b> and <b>&minus;zw</b>.
Step 3 is always executed. Step 4 is executed only if a new
IDAT is being created, and may be fine-tuned via the option
<b>&minus;zw</b>.</p>
<p style="margin-left:11%; margin-top: 1em">Extremely
exhaustive searches are not generally expected to yield
significant improvements in compression ratio, and are
recommended to advanced users only.</p>
<a name="EXAMPLES"></a>
<h2>EXAMPLES</h2>
<p style="margin-left:11%; margin-top: 1em"><tt>optipng
file1.png file2.gif file3.tif</tt></p>
<p style="margin-left:11%; margin-top: 1em"><tt>optipng
&minus;o5 file1.png file2.gif file3.tif</tt></p>
<p style="margin-left:11%; margin-top: 1em"><tt>optipng
&minus;i1 &minus;o7 &minus;v &minus;full &minus;sim
experiment.png</tt></p>
<a name="BUGS"></a>
<h2>BUGS</h2>
<p style="margin-left:11%; margin-top: 1em">Lossless image
reductions are not completely implemented. (This does NOT
affect the integrity of the output files.) Here are the
missing pieces:</p>
<p style="margin-left:22%; margin-top: 1em">&minus; The
color palette reductions are implemented only partially.
<br>
&minus; The bit depth reductions below 8, for grayscale
images, are not implemented yet.</p>
<p style="margin-left:11%; margin-top: 1em">TIFF support is
limited to uncompressed, PNG-compatible (grayscale, RGB and
RGBA) images.</p>
<p style="margin-left:11%; margin-top: 1em">Metadata is not
imported from the external image formats.</p>
<p style="margin-left:11%; margin-top: 1em">There is no
support for pipes or streams.</p>
<a name="SEE ALSO"></a>
<h2>SEE ALSO</h2>
<p style="margin-left:11%; margin-top: 1em"><b>png</b>(5),
<b>libpng</b>(3), <b>zlib</b>(3), <b>pngcrush</b>(1),
<b>pngrewrite</b>(1).</p>
<a name="STANDARDS"></a>
<h2>STANDARDS</h2>
<p style="margin-left:11%; margin-top: 1em">The files
produced by <b>OptiPNG</b> are compliant with
<b>PNG&minus;2003</b>: <br>
Glenn Randers-Pehrson et al. <i>Portable Network Graphics
(PNG) Specification, Second Edition</i>. <br>
W3C Recommendation 10 November 2003; ISO/IEC IS 15948:2003
(E). <tt><br>
http://www.w3.org/TR/PNG/</tt></p>
<a name="AUTHOR"></a>
<h2>AUTHOR</h2>
<p style="margin-left:11%; margin-top: 1em"><b>OptiPNG</b>
is written and maintained by Cosmin Truta.</p>
<p style="margin-left:11%; margin-top: 1em">This manual
page was originally written by Nelson A. de Oliveira for the
Debian Project. It was later updated by Cosmin Truta, and is
now part of the <b>OptiPNG</b> distribution.</p>
<hr>
</body>
</html>

View File

@@ -1,280 +0,0 @@
OPTIPNG(1) OPTIPNG(1)
NAME
OptiPNG - Advanced optimization program for Portable Network Graphics
(PNG)
SYNOPSIS
optipng [-? | -h | -help]
optipng [options...] files...
DESCRIPTION
The OptiPNG program shall attempt to optimize PNG files, i.e. reduce
their size to a minimum, without losing any information. In addition,
this program shall perform a suite of auxiliary functions like
integrity checks, metadata recovery and pixmap-to-PNG conversion.
The optimization attempts are not guaranteed to succeed. Valid PNG
files that cannot be optimized by this program are normally left
intact; their size will not grow. The user may request to override this
default behavior.
FILES
The input files are raster image files encoded either in PNG format
(the native format), or in an external format. The currently supported
external formats are GIF, BMP, PNM and TIFF.
OptiPNG processes each image file given in the command line as follows:
- If it is in PNG format:
Attempt to optimize the given file in-place. If optimization is
successful, or if the option -force is in effect, replace the
original file with its optimized version. The original file is
backed up if the option -keep is in effect.
- If it is in an external format:
Create an optimized PNG version of the given file. The output
file name is composed from the original file name and the .png
extension.
OPTIONS
General options
-?, -h, -help
Show a complete summary of options.
-o level
Select the optimization level.
The optimization level 0 enables a set of optimization opera-
tions that require minimal effort. There will be no changes to
image attributes like bit depth or color type, and no recompres-
sion of existing IDAT datastreams.
The optimization level 1 enables a single IDAT compression
trial. The trial chosen is what OptiPNG thinks it's probably the
most effective.
The optimization levels 2 and higher enable multiple IDAT com-
pression trials; the higher the level, the more trials.
The behavior and the default value of this option may change
across different program versions. Use the option -h to see the
details pertaining to your specific version.
-dir directory
Write output file(s) to directory.
-fix Enable error recovery. This option has no effect on valid input
files.
The program will spend a reasonable amount of effort to recover
as much data as possible, without increasing the output file
size, but the success cannot be generally guaranteed. The pro-
gram may even increase the file size, e.g., by reconstructing
missing critical data. Under this option, integrity shall take
precedence over file size.
When this option is not used, the invalid input files are left
unprocessed.
-force Enforce writing of a new output file.
This option overrides the program's decision not to write such
file, e.g. when the PNG input is digitally signed (using dSIG),
or when the PNG output becomes larger than the PNG input.
-keep Keep a backup of the modified file(s).
The files that use the backup names prior to the program execu-
tion are not overwritten.
-log file
Log messages to file. For safety reasons, file must have the
extension .log.
-out file
Write output file to file. The command line must contain
exactly one input file.
-preserve
Preserve file attributes (time stamps, file access rights, etc.)
where applicable.
-quiet Run in quiet mode.
These messages are still written to the log file if the option
-log is in effect.
-simulate
Run in simulation mode: perform the trials, but do not create
output files.
-snip Cut one image out of multi-image, animation or video file(s).
Depending on the input format, this may be either the first or
the most relevant (e.g. the largest) image.
-v Enable the options -verbose and -version.
-verbose
Run in verbose mode.
-version
Show copyright, version and build info.
-- Stop option switch parsing.
PNG encoding and optimization options
-f filters
Select the PNG delta filters.
The filters argument is specified as a rangeset (e.g. -f0-5),
and the default filters value depends on the optimization level
set by the option -o.
The filter values 0, 1, 2, 3 and 4 indicate static filtering,
and correspond to the standard PNG filter codes (None, Left, Up,
Average and Paeth, respectively). The filter value 5 indicates
adaptive filtering, whose effect is defined by the libpng(3)
library used by OptiPNG.
-full Produce a full report on IDAT. This option might slow down the
trials.
-i type
Select the interlace type (0-1).
If the interlace type 0 is selected, the output image shall be
non-interlaced (i.e. progressive-scanned). If the interlace type
1 is selected, the output image shall be interlaced using the
Adam7 method.
By default, the output shall have the same interlace type as the
input.
-nb Do not apply bit depth reduction.
-nc Do not apply color type reduction.
-np Do not apply palette reduction.
-nx Do not apply any lossless image reduction: enable the options
-nb, -nc and -np.
-nz Do not recode IDAT datastreams.
The IDAT optimization operations that do not require recoding
(e.g. IDAT chunk concatenation) are still performed.
This option has effect on PNG input files only.
-zc levels
Select the zlib compression levels used in IDAT compression.
The levels argument is specified as a rangeset (e.g. -zc6-9),
and the default levels value depends on the optimization level
set by the option -o.
The effect of this option is defined by the zlib(3) library used
by OptiPNG.
-zm levels
Select the zlib memory levels used in IDAT compression.
The levels argument is specified as a rangeset (e.g. -zm8-9),
and the default levels value depends on the optimization level
set by the option -o.
The effect of this option is defined by the zlib(3) library used
by OptiPNG.
-zs strategies
Select the zlib compression strategies used in IDAT compression.
The strategies argument is specified as a rangeset (e.g.
-zs0-3), and the default strategies value depends on the opti-
mization level set by the option -o.
The effect of this option is defined by the zlib(3) library used
by OptiPNG.
-zw size
Select the zlib window size (32k,16k,8k,4k,2k,1k,512,256) used
in IDAT compression.
The size argument can be specified either in bytes (e.g. 16384)
or kilobytes (e.g. 16k). The default size value is set to the
lowest window size that yields an IDAT output as big as if
yielded by the value 32768.
The effect of this option is defined by the zlib(3) library used
by OptiPNG.
Notes
Options may come in any order (except for --), before, after, or alter-
nating with file names. Option names are case-insensitive and may be
abbreviated to their shortest unique prefix.
Some options may have arguments that follow the option name, separated
by whitespace or the equal sign ('='). If the option argument is a num-
ber or a rangeset, the separator may be omitted. For example:
-out newfile.png <=> -out=newfile.png
-o3 <=> -o 3 <=> -o=3
-f0,3-5 <=> -f 0,3-5 <=> -f=0,3-5
Rangeset arguments are cumulative; e.g.
-f0 -f3-5 <=> -f0,3-5
-zs0 -zs1 -zs2-3 <=> -zs0,1,2,3 <=> -zs0-3
EXTENDED DESCRIPTION
The PNG optimization algorithm consists of the following steps:
1. Reduce the bit depth, the color type and the color palette of the
image. This step may reduce the size of the uncompressed image,
which, indirectly, may reduce the size of the compressed image
(i.e. the size of the output PNG file).
2. Run a suite of compression methods and strategies and select the
compression parameters that yield the smallest output file.
3. Store all IDAT contents into a single chunk, eliminating the over-
head incurred by repeated IDAT headers and CRCs.
4. Set the zlib window size inside IDAT to a mininum that does not
affect the compression ratio, reducing the memory requirements of
PNG decoders.
Not all of the above steps need to be executed. The behavior depends on
the actual input files and user options.
Step 1 may be customized via the no-reduce options -nb, -nc, -np and
-nx. Step 2 may be customized via the -o option, and may be fine-tuned
via the options -zc, -zm, -zs and -zw. Step 3 is always executed. Step
4 is executed only if a new IDAT is being created, and may be fine-
tuned via the option -zw.
Extremely exhaustive searches are not generally expected to yield sig-
nificant improvements in compression ratio, and are recommended to
advanced users only.
EXAMPLES
optipng file1.png file2.gif file3.tif
optipng -o5 file1.png file2.gif file3.tif
optipng -i1 -o7 -v -full -sim experiment.png
BUGS
Lossless image reductions are not completely implemented. (This does
NOT affect the integrity of the output files.) Here are the missing
pieces:
- The color palette reductions are implemented only partially.
- The bit depth reductions below 8, for grayscale images, are
not implemented yet.
TIFF support is limited to uncompressed, PNG-compatible (grayscale, RGB
and RGBA) images.
Metadata is not imported from the external image formats.
There is no support for pipes or streams.
SEE ALSO
png(5), libpng(3), zlib(3), pngcrush(1), pngrewrite(1).
STANDARDS
The files produced by OptiPNG are compliant with PNG-2003:
Glenn Randers-Pehrson et al. Portable Network Graphics (PNG) Specifi-
cation, Second Edition.
W3C Recommendation 10 November 2003; ISO/IEC IS 15948:2003 (E).
http://www.w3.org/TR/PNG/
AUTHOR
OptiPNG is written and maintained by Cosmin Truta.
This manual page was originally written by Nelson A. de Oliveira for
the Debian Project. It was later updated by Cosmin Truta, and is now
part of the OptiPNG distribution.
OptiPNG version 0.6.4 2010-March-14 OPTIPNG(1)

View File

@@ -1,634 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="Author" content="Cosmin Truţa">
<title>A guide to PNG optimization</title>
</head>
<body>
<h2>A guide to PNG optimization</h2>
<h3>1. Background</h3>
<h4>1.1 The PNG file format</h4>
<p>
The <a href="http://www.libpng.org/pub/png/">Portable Network Graphics</a>
(<b><i>PNG</i></b>) is a format for storing compressed raster graphics. The
compression engine is based on the <b><i>Deflate</i></b> method
[<a href="http://www.ietf.org/rfc/rfc1951">RFC1951</a>],
designed by
<a href="http://www.pkware.com/">PKWare</a>
and originally used in <b>PKZIP</b>.
</p>
<p>
The PNG format is defined by the
<a href="http://www.libpng.org/pub/png/spec/">PNG Specification</a>.
This specification was developed by an ad-hoc group named the
<a href="http://www.libpng.org/pub/png/">PNG Development Group</a>, and it is
both an International Standard (published under the formal name
ISO/IEC&nbsp;15948) and a W3C Recommendation.
</p>
<p>
PNG was initially intended as a superior, patent-free replacement of GIF. The
final outcome is a modern, extensible, reliable image format, capable to handle
an impressive number of image types (from 1-bit black-and-white images up to
48-bit RGB images with a full 16-bit alpha channel), and geared by a
significantly stronger lossless compression engine (typically 5-25% better than
GIF).
</p>
<p>
Unlike other lossless compression schemes, PNG compression does not depend
solely on the statistics of the input, but it may vary within wide limits,
depending on the compressor's implementation. A good PNG encoder must be
able to take informed decisions about the factors that affect the size of the
output. The purpose of this article is to provide information about these
factors, and to give advice on implementing efficient PNG encoders.
</p>
<h4>1.2 The PNG compression</h4>
<p>
The PNG compression works in a pipeline manner.
</p>
<p>
In the first stage, the image pixels are passed through a lossless arithmetic
transformation named <b><i>delta filtering</i></b>, or simply
<b><i>filtering</i></b>, and sent further as a (filtered) byte sequence.
Filtering does not compress or otherwise reduce the size of the data, but it
makes the data more compressible.
</p>
<p>
In the second stage, the filtered byte sequence is passed through the
Ziv-Lempel algorithm (LZ77), producing LZ77 codes that are further compressed
by the Huffman algorithm in the third and final stage. The combination of the
last two stages is referred to as the <b><i>Deflate compression</i></b>, a
widely-used, patent-free algorithm for universal, lossless data compression.
The maximum size of the LZ77 sliding window in Deflate is 32768 bytes, and the
LZ77 matches can be between 3 and 258 bytes long.
</p>
<p>
A complete description of the PNG compression is beyond the scope of this
guide. The PNG Specification describes the format completely, and provides
a complete list of references to the underlying technologies.
</p>
<h3>2. Factors that affect the PNG file size</h3>
<div>
Like any other compression scheme, PNG compression depends on the statistics
of the input data. In addition, it depends on the following PNG-specific
parameters:
</div>
<ol>
<li>
The PNG image type
</li>
<li>
The PNG delta filters
</li>
<li>
The strategy of searching LZ77 matches
</li>
<li>
The size of the Huffman buffers inside the Deflate encoder
</li>
</ol>
<p>
Depending on how these parameters are chosen by the implementation, PNG
compression may vary within wide limits. The process of selecting the best
configuration is computationally infeasible, but heuristics to select a
satisfactory configuration are available. The problem of improving these
heuristics constitutes an interesting subject for research.
</p>
<h4>2.1 The PNG image type</h4>
<p>
The type of a PNG image is defined in the <b><code>IHDR</code></b> image
header. The image has a certain bit depth, up to 16 bits per sample, and a
certain color type, from Grayscale to RGB+Alpha. If two PNG files of different
types represent exactly the same image, each file can be regarded as a lossless
transformation of the other. A lossless transformation can reduce the
<i>uncompressed</i> stream, and such a transformation is named <b><i>image
reduction</i></b>. In most cases, image reductions are capable of reducing the
<i>compressed</i> stream (which is, in fact, our interest), as an indirect
effect of reducing the size of the compressor's input.
</p>
<div>
The possible image reductions are:
</div>
<ul>
<li>
<i>Bit depth reduction</i>
<br>
The bit depth can be reduced to a minimum value that is acceptable for all
samples. For example, if all sample values in a 16-bit image have the form
(256+1)*<i>n</i>, (e.g. #0000, #2323, #FFFF), then the bit depth can be
reduced to 8, and the new sample values will become <i>n</i>, (e.g. #00, #23,
#FF).
</li>
<li>
<i>Color type reduction</i>
<br>
- If an RGB image has 256 distinct colors or less, it can be reencoded as a
Palette image.
<br>
- If an RGB or Palette image has only gray pixels, it can be reencoded as
Grayscale.
<br>
A color type reduction can also enable a bit depth reduction.
</li>
<li>
<i>Color palette reduction</i>
<br>
If the color palette contains redundant entries (i.e. duplicate entries that
indicate the same RGB value) or sterile entries (i.e. entries that do not
have a correspondent in the raw pixel data), these entries can be removed.
<br>
A color palette reduction can also enable a bit depth reduction.
</li>
<li>
<i>Alpha channel reduction</i>
<br>
If all pixels in a Grayscale+Alpha or an RGB+Alpha image are fully opaque
(i.e. all alpha components are equal to 2^<sup>bitdepth</sup>-1), or if the
transparency information can be stored entirely in a (much cheaper)
<b><code>tRNS</code></b> chunk, the alpha channel can be stripped.
</li>
</ul>
<p>
There are, however, a few cases when some image type reductions do not
necessarily lead to the reduction of the compressed stream. The
<a href="http://www.cs.toronto.edu/~cosmin/pngtech/">PNG-Tech</a> site contains
experimental analyses of these possibilities; for example, see the article
<a href="8bpp.html">8 bits per pixel in paletted images</a>.
</p>
<p>
Interlacing, useful for a faster, progressive rendering, is another component
of the PNG image type that affects compression. In an interlaced stream, the
samples corresponding to neighboring pixels are stored far away, hence the data
in it is less correlated and less compressible. Unlike JPEG, where interlacing
may improve the compression slightly, the PNG interlacing degrades the
compression significantly.
</p>
<h4>2.2 The PNG delta filters</h4>
<p>
The role of filtering can be illustrated in the following example. Assume the
sequence 2, 3, 4, 5, 6, 7, 8, 9. Although it has much redundancy, the sequence
is not compressible by a Ziv-Lempel compressor, nor by a Huffman compressor.
However, if one makes a simple and reversible transformation, replacing each
value with the numerical difference between it and the value to its left, the
sequence becomes 2, 1, 1, 1, 1, 1, 1, 1, which is highly compressible.
</p>
<p>
The PNG format employs five types of filters: <b><i>None</i></b>,
<b><i>Left</i></b>, <b><i>Up</i></b>, <b><i>Average</i></b>, and
<b><i>Paeth</i></b>. The first filter leaves the original data intact, and the
other four are subtracting from each pixel a value that involves the
neighbor pixels from the left, up, and/or the upper left.
</p>
<p>
A certain filter is assigned to each row, and is applied to all pixels from
that row. Therefore, an image can be delta-filtered in a huge number of
possible configurations (5 ^ <sup><i>height</i></sup>), and each configuration
leads to a different compressed output. Two different filter configurations may
make a difference in the compressed file size by a couple of factors, so a
careful choice of filters is of paramount importance.
</p>
<p>
It is possible to apply a single filter to all rows, or to apply different
filters to different rows. In the former case, the filtering process is
<b><i>fixed</i></b>; in the latter, it is <b><i>adaptive</i></b>.
</p>
<div>
While an exhaustive search is unfeasible, the PNG Specification suggests a
heuristic filtering strategy:
</div>
<ul>
<li>
If the image type is Palette, or the bit depth is smaller than 8, then
do not filter the image (i.e. use fixed filtering, with the filter
<i>None</i>).
</li>
<li>
(The other case) If the image type is Grayscale or RGB (with or without
Alpha), and the bit depth is not smaller than 8, then use adaptive filtering
as follows: <i>independently for each row</i>, apply all five filters and
select the filter that produces the smallest sum of absolute values per row.
</li>
</ul>
<p>
Cases where the above heuristics are less than optimal are shown on the
<a href="http://www.cs.toronto.edu/~cosmin/pngtech/">PNG-Tech</a>
site; for example, see
<a href="better-filtering.html">Brute-force vs. heuristic filtering</a>.
</p>
<h4>2.3 The strategy of searching LZ77 matches</h4>
<p>
The Ziv-Lempel algorithm works under the assumption that contiguous sequences
appear repeatedly in the input stream. If the sequence to be encoded matches
one or more sequences already present in the sliding history window, the
encoder sends a LZ77 pair (<i>distance</i>, <i>length</i>) that points to the
<i>closest</i> match. In most LZ77 incarnations, including Deflate, smaller
distance codes are encoded more concisely.
</p>
<p>
In Deflate, in particular, the regular (non-matched) symbols, and the match
lengths, are sent to the same Huffman coder, while the match distances are sent
to a separate Huffman coder. If the LZ77 matches fall between the accepted
boundaries (i.e. they are not shorter than 3 and not longer than 258), a greedy
strategy will accept them as a replacement for the symbols to which they
correspond.
</p>
<p>
The greedy strategy is preferable when compressing text files, or many types of
binary files, but it may be suboptimal when compressing filtered data, such as
the byte strings that come from a PNG filter. Filtered data consist mostly of
small values with a pseudo-random distribution. Therefore, in certain
situations, it may be desirable to favor the encoding of individual symbols,
even if matches that may replace these symbols exist.
</p>
<p>
The
<a href="http://www.zlib.org/">zlib Reference Library</a>
is a reference implementation of Deflate, which is further used by the
<a href="http://www.libpng.org/pub/png/libpng.html">PNG Reference Library</a>.
By default, <b>zlib</b> selects the greedy strategy, but the user is able to
specify his or her custom preference via the <code>strategy</code> parameter.
This parameter can take one of the following values:
<br>
- <code>Z_DEFAULT_STRATEGY = 0</code>, the default greedy search strategy.
<br>
- <code>Z_FILTERED = 1</code>, a strategy in which the matches are accepted
only if their length is 6 or bigger.
<br>
- <code>Z_HUFFMAN_ONLY = 2</code>, a fast strategy in which the Ziv-Lempel
algorithm is entirely bypassed, and all the symbols from the input are encoded
directly by the Huffman coder.
<br>
- <code>Z_RLE = 3</code> (appeared in the <b>zlib-1.2.x</b> series), a fast
strategy in which the LZ77 algorithm is essentially reduced to the Run-Length
Encoding algorithm. In other words, the matches are accepted only if their
distance is 1. For example, the 10-symbol sequence "<code>aaaaaaaaaa</code>"
can be LZ77-encoded as
['<code>a</code>', (<i>distance</i>=1, <i>length</i>=9)];
by removing <i>distance</i>=1 from the picture, this encoding can be regarded
as a peculiar run-length encoding (which differs from the classic RLE by using
<i>length</i>=9 instead of <i>count</i>=10).
<br>
The <code>strategy</code> parameter affects only the compression ratio. It does
not affect the correctness of the compressed output, even if it is set to an
inappropriate value.
</p>
<p>
It was experimentally observed that the LZ77 search is occasionally capable of
producing smaller PNGs if it is less exhaustive. The reason behind this act
resides in the same category of "strategic searches" discussed here.
Unfortunately, there is no known method of anticipating which search level
(from the fastest and the least exhaustive, to the slowest and the most
exhaustive) is better, other than assuming "the most exhaustive is better in
most cases".
</p>
<p>
Unfortunately, even a "filtered" strategy does not always produce better
results than a "greedy" strategy on filtered input, and the only known method
to obtain the best combination is by multiple trials. Experiments and
measurements can, again, be found on the
<a href="http://www.cs.toronto.edu/~cosmin/pngtech/">PNG-Tech</a>
site; for example, see the original
<a href="z_rle.html">Z_RLE strategy proposal</a>.
</p>
<h4>2.4 The size of Huffman buffers</h4>
<p>
As mentioned earlier, the entropy encoder inside the Deflate method is the
static Huffman algorithm. The output of LZ77 is fed into a buffer which is
occasionally flushed by sending a static Huffman tree followed by all the
Huffman codes, to the output of Deflate. After this, both the buffer and the
Huffman tree are reset, waiting for the subsequent LZ77 codes to come and
refill the buffer.
</p>
<blockquote>
The Deflate specification refers to <i>dynamic Huffman codes</i>. However, this
is a misnomer, in which the term <i>dynamic</i> is used in contrast to the
<i>fixed</i> Huffman codes. The fixed Huffman codes are simply built according
to a predefined Huffman tree, without regard to the actual symbol frequencies.
The dynamic Huffman codes referred to by the Deflate specification are NOT
built by the dynamic Huffman algorithm, as defined, for example, by Faller,
Gallager and Knuth (the FGK algorithm), or by Vitter (the V algorithm).
The predefined Huffman tree was introduced in <b>PKZIP</b> as a fast
compression alternative, but it produces poor results even on text, and it is
almost useless in PNG compression. Still, a PNG stream that contains codes
built by the fixed (predefined) Huffman tree, is a valid stream, and a
compliant PNG reader must decode this stream correctly.
</blockquote>
<p>
It is desirable to establish the buffer boundaries so that sequences conforming
to the same probability model are fit in the same Huffman buffer. Methods for
approaching these boundaries exist, but they are not used in the mainstream
Deflate implementation(s). Instead, the buffers are flushed when a limit
(typically, 16k LZ77 codes) is reached. This is, however, a fast approach, and
the results are satisfactory.
</p>
<p>
The size of Huffman buffers is indirectly determined by the encoder's memory
(usage) level. For this reason, certain memory levels might be good for certain
types of images.
</p>
<h3>3. PNG (lossless) optimization programs</h3>
<p>
The multitude of PNG encoding programs is listed at
<a href="http://www.libpng.org/pub/png/pngapps.html">http://www.libpng.org/pub/png/pngapps.html</a>.
Their performance varies as much as the range of possible compression ratios;
the good encoders are at least applying the filtering heuristics, described
briefly in the PNG Specification, and illustrated above.
<br>
Some programs gain extra compression by discarding some of the data in the
input images (so these programs are <i>lossy</i>!)
</p>
<p>
This section contains the small list of <b><i>PNG optimization programs</i></b>
that show a particular concern towards obtaining a file size as small as
possible. They work by performing repeated compression trials, applying various
parameter sets, and selecting the parameter set that yields the smallest
compressed output.
</p>
<ul>
<li>
<p>
<b>pngrewrite</b> by Jason Summers, available at
<a href="http://www.pobox.com/~jason1/pngrewrite/">http://www.pobox.com/~jason1/pngrewrite</a>,
is an open-source program that performs lossless image reductions.
It works best in conjunction with <b>pngcrush</b> (see below); the user
should run <b>pngcrush</b> <i>after</i> <b>pngrewrite</b>.
</p>
</li>
<li>
<p>
<b>pngcrush</b> by Glenn Randers-Pehrson, available at
<a href="http://pmt.sourceforge.net/pngcrush/">http://pmt.sourceforge.net/pngcrush</a>,
is an open-source program that iterates over PNG filters and zlib (Deflate)
parameters, compresses the image repeatedly using each parameter
configuration, and chooses the configuration that yields the smallest
compressed (IDAT) output.
At the user's option, the program can explore few (below 10) or many (a
brute-force traversal over more than 100) configurations. The method of
selecting the parameters for "few" trials is particularly effective, and the
use of a brute-force traversal is generally not recommended.
</p>
<p>
In addition, <b>pngcrush</b> offers a multitude of extra features, such as
recovery of erroneous PNG files (e.g. files containing bad CRCs), and
chunk-level editing of PNG meta-data.
</p>
</li>
<li>
<p>
<b>OptiPNG</b> by Cosmin Truţa, available at
<a href="http://www.cs.toronto.edu/~cosmin/pngtech/optipng/">http://www.cs.toronto.edu/pngtech/optipng</a>,
is a newer open-source program, inspired from <b>pngcrush</b>, but designed
to be more flexible and to run faster.
Unlike <b>pngcrush</b>, <b>OptiPNG</b> performs the trials entirely in
memory, and writes only the final output file on the disk. Moreover, it
offers multiple optimization presets to the user, who can choose among a
range of options from "very few trials" to "very many trials" (in contrast to
the coarser "smart vs. brute" option offered by <b>pngcrush</b>).
</p>
<p>
It is important to mention that the achieved compression ratio is less and
less likely to improve when higher-level presets (trigerring more trials)
are being used. Even if the program is capable of searching automatically
over more than 200 configurations (and the advanced users have access to more
than 1000 configurations!), a preset that selects around 10 trials should be
satisfactory for most users. Furthermore, a preset that selects between
30-40 trials <i>should</i> be satisfactory for all users, for it is very,
very unlikely to be beaten significantly by any wider search. The rest of the
trial configurations are offered rather as a curiosity (but they were used in
the experimentation from which we concluded they are indeed useless!)
</p>
</li>
<li>
<p>
<b>AdvanceCOMP</b> by Andrea Mazzoleni is a set of tools for optimizing
ZIP/GZIP, PNG and MNG files, based on the powerful <b>7-Zip</b> deflation
engine. The name of the PNG optimization tool is <b>AdvPNG</b>. At the time
of this writing, <b>AdvPNG</b> does not perform image reductions, so the use
of <b>pngrewrite</b> or <b>OptiPNG</b> prior to optimiziation may be
necessary. However, given the effectivenes of <b>7-Zip</b> deflation,
<b>AdvanceCOMP</b> is a powerful contender.
</p>
<p>
The <b>AdvanceCOMP</b> tool set is a part of the <b>AdvanceMAME</b> project,
available at
<a href="http://advancemame.sourceforge.net/">http://advancemame.sourceforge.net</a>.
</p>
</li>
<li>
<p>
<b>PNGOut</b> by Ken Silverman, available at
<a href="http://advsys.net/ken/utils.htm">http://advsys.net/ken/utils.htm</a>,
is a freely-available compiled program (no source code), running on
Windows and Linux. According to our tests, the compression ratio achieved by
<b>PNGOut</b> is comparable to that of <b>AdvPNG</b>.
Unfortunately, due to the lack of information, we cannot say much about this
tool.
</p>
<p>
A nice GUI frontend for <b>PNGOut</b>, named <b>PNGGauntlet</b>, is
available at
<a href="http://www.numbera.com/software/pnggauntlet.aspx">http://www.numbera.com/software/pnggauntlet.aspx</a>.
</p>
</li>
</ul>
<h3>4. An extra note on losslessness</h3>
<p>
What is lossless PNG optimization, after all? This is a straightforward
question, whose answer is intuitive, yet not so straightforward.
</p>
<p>
Losslessness in the strictest sense, where no information whatsoever is lost,
can only be achieved by leaving the original file (<i>any</i> file) intact, or
by transforming it (e.g. compressing it, encrypting it) in such a way that
there is an inverse transformation which recovers it completely, bit by bit.
</p>
<p>
In the case of PNG images, this condition of strict losslessness has little
relevance to the casual graphics user, and is, therefore, too strong.
There are instances where strict losslessness is required; for example, when
handling certified PNG files whose integrity is guaranteed by an external
checksum like <b>MD5</b> or <b>SHA</b>, or by a digital signature such as
<b><code>dSIG</code></b>. Most of the time, however, it is desirable to relax
the notion of PNG losslessness, to the extent of not losing any information
that pertains to the <i>rendered image</i> and to the
<i>semantic value of the metadata</i> that accompanies the image. This allows
the user to concentrate on what is really important when it comes to preserving
the contents of a PNG image, and enables the concept of PNG optimization tools.
</p>
<blockquote>
A <b><i>lossless transform</i></b> of a PNG image file is a transform which
fully preserves the <i>rendered</i> RGB triples (the RGB triples that come
either directly, or from a palette index, or from a gray->RGB expansion), the
<i>rendered</i> transparency (the alpha samples that come either directly, or
from a <b><code>tRNS</code></b> chunk, or the implicit 100% opacity assumed due
to the lack of any explicit transparency information), the <i>order of
rendering</i> (sequential or interlaced), and the semantics contained by the
ancillary chunks.
</blockquote>
<div>
This definition allows the execution of the above-mentioned image reduction
operations, and the recompression of <b><code>IDAT</code></b>. It also allows
the alteration or the elimination of other pieces of information that are
technically valid, but have no influence on any presentation of the image
pixels:
</div>
<ul>
<li>
The information that pertains to <b><i>Deflate</i></b> streams, either inside
<b><code>IDAT</code></b>, or in other compressed chunks like
<b><code>zTXt</code></b>, <b><code>iTXt</code></b> or
<b><code>iCCP</code></b>; e.g. the LZ77 window size, the type and size of
<b><i>Deflate</i></b> blocks, etc. (The only thing that matters is that the
decompressed byte sequence must remain the same.)
</li>
<li>
The order of palette entries inside a <b><code>PLTE</code></b> chunk. (When
changing this order, the information that depends on it, such as the
palette-encoded pixels or the <b><code>tRNS</code></b> information, must be
updated accordingly.)
</li>
<li>
RGB triples that do not correspond to any pixel in the actual image, but are
stored in a <b><code>tRNS</code></b> chunk.
</li>
<li>
Fully opaque <b><code>tRNS</code></b> entries in a palette image.
</li>
<li>
Gamma correction (<b><code>gAMA</code></b>) or significant bit
(<b><code>sBIT</code></b>) information inside an image that consists
exclusively of samples whose intensity is either minimum (0) or maximum
(2^<sup>bitdepth</sup>-1).
</li>
<li>
The fact that a textual comment is stored uncompressed in a
<b><code>tEXt</code></b> chunk, or compressed in a <b><code>zTXt</code></b>
chunk, or with no translation in an <b><code>iTXt</code></b> chunk.
</li>
<li>
Etcetera.
</li>
</ul>
<p>
If any of the discardable information is important in a particular application,
and lossless PNG optimization is still desirable, it is recommended to store
this information in ancillary chunks, rather than hack it inside critical
chunks. For example, if sterile palette entries are necessary (e.g. for later
editing stages), it is recommended to store them inside a suggested palette
(<b><code>sPLT</code></b>) chunk, rather than keeping them inside
<b><code>PLTE</code></b>.
</p>
<h3>5. Selective bibliography</h3>
<p>
Besides the discussed specifications, the references below provide essential
information necessary to comprehend the contents of this article.
</p>
<ul>
<li>
Thomas Boutell, Glenn Randers-Pehrson et al.
<i>Portable Network Graphics (PNG) Specification, Second Edition</i>.
ISO/IEC 15948:2003(E); W3C Recommendation 10 November 2003.
</li>
<li>
David A. Huffman.
A method for the construction of minimum redundancy codes.
In <i>Proceedings of the Institute of Radio Engineers</i>,
vol. 40, no. 9, pp. 1098-1101, September 1952.
</li>
<li>
Jacob Ziv and Abraham Lempel.
A universal algorithm for data compression.
<i>IEEE Transactions on Information Theory</i>,
vol. IT-23, no. 3, pp. 337-343, May 1977.
<br>
<font size="-1">
Due to a historical accident, the famous algorithm is better-known as the
"Lempel-Ziv (LZ) algorithm", even though the "Ziv-Lempel algorithm" is a
more legitimate name.
</font>
</li>
<li>
Greg Roelofs.
<i>PNG: The definitive guide</i>.
O'Reilly and Associates, 1999.
</li>
</ul>
<hr>
<address>
<font size="-1">
Copyright &copy; 2003-2008 Cosmin Truţa. Permission to distribute freely.
<br>
Appeared: 7&nbsp;Apr&nbsp;2003.
<br>
Last updated: 10&nbsp;May&nbsp;2008.
</font>
</address>
</body>
</html>

View File

@@ -1,325 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="Author" content="Cosmin Truţa">
<title>Thanks!</title>
</head>
<body>
<h2>Acknowledgements</h2>
<div>
The author is indebted to the following people.
OptiPNG would not exist without their work.
<p>
<table border="0" width="100%">
<tbody>
<tr>
<td width="25%">Mark Adler</td>
<td>for developing the zlib library</td>
</tr>
<tr>
<td width="25%">Thomas Boutell</td>
<td>for the idea of creating the PNG image format (it's all his fault!)</td>
</tr>
<tr>
<td width="25%">Adam M. Costello</td>
<td>for co-developing cexcept, an exception-handling interface for C</td>
</tr>
<tr>
<td width="25%">Jean-loup Gailly</td>
<td>for devising a patent-free deflation algorithm
and for developing the zlib library</td>
</tr>
<tr>
<td width="25%">Phil Katz</td>
<td>for inventing ZIP (PKZip) and the deflation algorithm</td>
</tr>
<tr>
<td width="25%">David Koblas</td>
<td>GIF support is derived from the giftopnm tool</td>
</tr>
<tr>
<td width="25%">Miyasaka Masaru</td>
<td>BMP support is derived from the bmptopng tool</td>
</tr>
<tr>
<td width="25%">David Salomon</td>
<td>for writing the most comprehensive data compression reference book</td>
</tr>
<tr>
<td width="25%">Jason Summers</td>
<td>image reductions are inspired from the pngrewrite tool</td>
</tr>
<tr>
<td width="25%">Glenn Randers-Pehrson</td>
<td>OptiPNG is inspired from the pngcrush tool(!)</td>
</tr>
<tr>
<td width="25%">The PNG Development Group</td>
<td>for developing the PNG format and the libpng library
and also for countless help via the emailing list :-)</td>
</tr>
<tr>
<td width="25%">The Information Theory founders</td>
<td>Shannon, Huffman, Ziv, Lempel et al., you will never be forgotten!</td>
</tr>
</tbody>
</table>
</div>
<p>
<hr>
<p>
<div>
There are also many people who contributed to the OptiPNG project.
The author is grateful to all of them.
<br>
This list is by no means complete. If you made a contribution, but your name is
not listed here, please don't be shy and
<a href="http://sourceforge.net/sendmessage.php?touser=24402">let him know</a>.
<br>
The author is particularly aware of the ever-increasing grup of amazing
volunteers who either create new ports and packages, or take over the
maintenance of the existing ones. They are unsung heroes. Regardless whether
they are on this list or not (yet), a big THANKS goes to them!
<p>
<table border="0" width="100%">
<tbody>
<tr>
<td width="25%">Peter Ahlstrom</td>
<td>for experimenting with the zlib parameters,
and for providing useful test data</td>
</tr>
<tr>
<td width="25%">Emmanuel Andry</td>
<td>for maintaining the Mandriva Linux port</td>
</tr>
<tr>
<td width="25%">Piotr Bandurski</td>
<td>for maintaining the Amiga port,
and for suggesting a feature improvement</td>
</tr>
<tr>
<td width="25%">Fabien Barbier</td>
<td>for fixing a Unicode build issue on Windows</td>
</tr>
<tr>
<td width="25%">Fabrizio Bartoloni</td>
<td>for maintaining the MorphOS port</td>
</tr>
<tr>
<td width="25%">Pascal Bleser</td>
<td>for maintaining the SUSE Linux port</td>
</tr>
<tr>
<td width="25%">Stefan Brüns</td>
<td>for contributing a security fix</td>
</tr>
<tr>
<td width="25%">James Buren</td>
<td>for maintaining the Frugalware Linux port</td>
</tr>
<tr>
<td width="25%">Adam Ciarcinski</td>
<td>for maintaining the pkgsrc package</td>
</tr>
<tr>
<td width="25%">James H. Cloos, Jr.</td>
<td>for being the first user to report a defect</td>
</tr>
<tr>
<td width="25%">Christian Davideck</td>
<td>for reporting a defect</td>
</tr>
<tr>
<td width="25%">Andrew C. E. Dent</td>
<td>for experimenting with various compression parameters,
and for providing useful test data</td>
</tr>
<tr>
<td width="25%">Matthew Fearnley</td>
<td>for reporting several defects and limitations,
and for contributing a reduction improvement</td>
</tr>
<tr>
<td width="25%">Petr Gajdos</td>
<td>for maintaining the SUSE Linux port</td>
</tr>
<tr>
<td width="25%">Nicolas Le Gland</td>
<td>for reporting a defect</td>
</tr>
<tr>
<td width="25%">Tero Grundström</td>
<td>for reporting a build problem</td>
</tr>
<tr>
<td width="25%">Larry Hastings</td>
<td>for suggesting a performance improvement, for reporting a defect,
and for providing useful test data</td>
</tr>
<tr>
<td width="25%">Tristan Heaven</td>
<td>for maintaining the Gentoo Linux port</td>
</tr>
<tr>
<td width="25%">Jukka Heino</td>
<td>for maintaining the Crux Linux port</td>
</tr>
<tr>
<td width="25%">Max Horn</td>
<td>for maintaining the Mac OS X (Fink) port</td>
</tr>
<tr>
<td width="25%">Thomas Hurst</td>
<td>for maintaining the FreeBSD port</td>
</tr>
<tr>
<td width="25%">Joachim Kluge</td>
<td>for reporting a defect</td>
</tr>
<tr>
<td width="25%">Bill Koch</td>
<td>for reporting a defect</td>
</tr>
<tr>
<td width="25%">Niels de Koning</td>
<td>for contributing memory leak fixes</td>
</tr>
<tr>
<td width="25%">Michael Krishtopa</td>
<td>for reporting a defect</td>
</tr>
<tr>
<td width="25%">Vincent Lefevre</td>
<td>for maintaining the Mac OS X DarwinPort,
and for suggesting a feature</td>
</tr>
<tr>
<td width="25%">Vitaly Lipatov</td>
<td>for maintaining the ALT Linux port</td>
</tr>
<tr>
<td width="25%">Alexander Lucas</td>
<td>for suggesting a feature</td>
</tr>
<tr>
<td width="25%">Till Maas</td>
<td>for maintaining the Fedora Linux port,
and for valuable contributions and feedback</td>
</tr>
<tr>
<td width="25%">Brian McQuade</td>
<td>for contributing a security fix</td>
</tr>
<tr>
<td width="25%">Nehal Mistry</td>
<td>for suggesting various features</td>
</tr>
<tr>
<td width="25%">Dirk Mueller</td>
<td>for maintaining the SUSE Linux port</td>
</tr>
<tr>
<td width="25%">Gustavo De Nardin</td>
<td>for maintaining the Mandriva Linux port</td>
</tr>
<tr>
<td width="25%">Nelson A. de Oliveira</td>
<td>for maintaining the Debian Linux port,
and for valuable contributions and feedback</td>
</tr>
<tr>
<td width="25%">Tavis Ormandy</td>
<td>for maintaining the Gentoo Linux port</td>
</tr>
<tr>
<td width="25%">Martin Packman</td>
<td>for reporting a defect</td>
</tr>
<tr>
<td width="25%">Dimitri Papadopoulos</td>
<td>for reporting a defect</td>
</tr>
<tr>
<td width="25%">Aaron Reitz</td>
<td>for reporting a platform-specific build problem</td>
</tr>
<tr>
<td width="25%">Ryan Schenk</td>
<td>for writing PNGpong, a Dashboard widget for Mac OS X</td>
</tr>
<tr>
<td width="25%">Ville Skyttä</td>
<td>for maintaining the Fedora Linux port</td>
</tr>
<tr>
<td width="25%">Roy Tam</td>
<td>for reporting a defect</td>
</tr>
<tr>
<td width="25%">Juhapekka Tolvanen</td>
<td>for suggesting various script improvements</td>
</tr>
<tr>
<td width="25%">Dmitry Vlasko</td>
<td>for writing a configurable Windows shell integration utility</td>
</tr>
<tr>
<td width="25%">Funda Wang</td>
<td>for maintaining the Mandriva Linux port</td>
</tr>
<tr>
<td width="25%">Liang Zhao</td>
<td>for reporting a platform-specific build problem</td>
</tr>
<tr>
<td width="25%">[akJ]</td>
<td>for writing an Eclipse RCP utility</td>
</tr>
<tr>
<td width="25%">[amake]</td>
<td>for writing pngcrusher, a Mac OS X front-end</td>
</tr>
<tr>
<td width="25%">[Baldelario]</td>
<td>for maintaining the Slackware Linux port</td>
</tr>
<tr>
<td width="25%">[I Like Pi]</td>
<td>for writing a configurable Paint.NET plugin</td>
</tr>
<tr>
<td width="25%">[LaughingMan]</td>
<td>for suggesting a feature, and for reporting a defect</td>
</tr>
<tr>
<td width="25%">[warriant]</td>
<td>for suggesting the use of UPX to pack the Windows executable</td>
</tr>
</tbody>
</table>
</div>
<p>
<hr>
<div>
Last updated: 14&nbsp;Mar&nbsp;2010 by Cosmin Truţa.
<br>
<a href="http://optipng.sourceforge.net/">&lt;&lt;&nbsp;<b>OptiPNG Home Page</b></a>
</div>
</body>
</html>

View File

@@ -1,57 +0,0 @@
OptiPNG - TO-DO list
====================
- Compression improvements:
Use zlib's deflateTune().
Use 7zip's powerful deflation engine.
(This is not possible with libpng, so a custom encoder is needed.)
- Speed improvements:
Avoid repeated filtering when trying a filter value more than once.
(This is not possible with libpng, so a custom encoder is needed.)
- Text chunk optimization:
Smart selection between tEXt and zTXt. Similarly for iTXt.
- More file recovery features.
- Input from stdin; output to stdout.
- Optimization of an entire directory, with and without subdirectory
recursion:
optipng dir/
optipng -recurse dir/
Currently it is possible to optimize an entire directory as:
optipng dir/*.png
provided that file globbing works, either at the shell level (Unix)
or in the program (linked with wildargs.obj on Windows).
- Improved support for reading external image formats
(e.g. compressed TIFF or other image formats).
- Support for conversion to a desired bit depth and color type:
optipng -b16 -c6 ...
- Support for handling metadata, e.g.:
optipng -meta set:tEXt=<keyword>,<text> # add/update chunk
optipng -meta set:sRGB=0 # add/update chunk
optipng -meta select:all # keep all chunks
optipng -meta reject:all # delete all chunks
optipng -meta select:std2003 # keep all standard chunks
optipng -meta select:public # keep all public chunks
optipng -meta reject:private # delete all private chunks
optipng -meta reject:hIST,sPLT # delete hIST and sPLT
optipng -meta select:visual # keep gAMA, cHRM, sRGB, ...
optipng -meta reject:visual # delete gAMA, cHRM, sRGB, ...
optipng -meta select:textual # keep tEXt, zTXt, iTXt
optipng -meta reject:textual # delete tEXt, zTXt, iTXt
optipng -meta reject:gif # delete gIFg, gIFt, gIFx
optipng -meta load:<file> # load chunks from file
optipng -meta store:<file> # store chunks in file
- Parallelization on multi-processor/multi-core machines.
- A shared library (e.g. optipng.dll), to facilitate the development of
PNG-optimizing GUI applications and plugins.

View File

@@ -1,8 +1,8 @@
* {
float: none;
background: #fff;
float: none; /* Screens are not big enough to account for floats */
background: #fff; /* As much contrast as possible */
color: #000;
}
/* Slightly reducing font size to reduce need to scroll */
body { font-size: 80%; }

View File

@@ -1,89 +1,171 @@
/* HTML5 ✰ Boilerplate */
/**
* HTML5 ✰ Boilerplate
*
* style.css contains a reset, font normalization and some base styles.
*
* Credit is left where credit is due.
* Much inspiration was taken from these projects:
* - yui.yahooapis.com/2.8.1/build/base/base.css
* - camendesign.com/design/
* - praegnanz.de/weblog/htmlcssjs-kickstart
*/
html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre,
/**
* html5doctor.com Reset Stylesheet (Eric Meyer's Reset Reloaded + HTML5 baseline)
* v1.6.1 2010-09-17 | Authors: Eric Meyer & Richard Clark
* html5doctor.com/html-5-reset-stylesheet/
*/
html, body, div, span, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp,
small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li,
fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, figcaption, figure, footer, header, hgroup,
menu, nav, section, summary, time, mark, audio, video {
margin:0;
padding:0;
border:0;
outline:0;
font-size:100%;
vertical-align:baseline;
background:transparent;
}
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
display:block;
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, figcaption, figure,
footer, header, hgroup, menu, nav, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
nav ul { list-style:none; }
blockquote, q { quotes:none; }
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
blockquote, q { quotes: none; }
blockquote:before, blockquote:after,
q:before, q:after { content:''; content:none; }
a { margin:0; padding:0; font-size:100%; vertical-align:baseline; background:transparent; }
ins { background-color:#ff9; color:#000; text-decoration:none; }
mark { background-color:#ff9; color:#000; font-style:italic; font-weight:bold; }
q:before, q:after { content: ''; content: none; }
ins { background-color: #ff9; color: #000; text-decoration: none; }
mark { background-color: #ff9; color: #000; font-style: italic; font-weight: bold; }
del { text-decoration: line-through; }
abbr[title], dfn[title] { border-bottom:1px dotted; cursor:help; }
table { border-collapse:collapse; border-spacing:0; }
hr { display:block; height:1px; border:0; border-top:1px solid #ccc; margin:1em 0; padding:0; }
input, select { vertical-align:middle; }
abbr[title], dfn[title] { border-bottom: 1px dotted; cursor: help; }
table { border-collapse: collapse; border-spacing: 0; }
hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }
input, select { vertical-align: middle; }
body { font:13px/1.231 sans-serif; *font-size:small; }
/**
* Font normalization inspired by YUI Library's fonts.css: developer.yahoo.com/yui/
*/
body { font:13px/1.231 sans-serif; *font-size:small; } /* Hack retained to preserve specificity */
select, input, textarea, button { font:99% sans-serif; }
/* Normalize monospace sizing:
en.wikipedia.org/wiki/MediaWiki_talk:Common.css/Archive_11#Teletype_style_fix_for_Chrome */
pre, code, kbd, samp { font-family: monospace, sans-serif; }
body, select, input, textarea { color: #444; }
h1,h2,h3,h4,h5,h6 { font-weight: bold; }
/**
* Minimal base styles.
*/
/* Always force a scrollbar in non-IE */
html { overflow-y: scroll; }
/* Accessible focus treatment: people.opera.com/patrickl/experiments/keyboard/test */
a:hover, a:active { outline: none; }
a, a:active, a:visited { color: #607890; }
a:hover { color: #036; }
ul, ol { margin-left: 1.8em; }
ul, ol { margin-left: 2em; }
ol { list-style-type: decimal; }
nav ul, nav li { margin: 0; }
/* Remove margins for navigation lists */
nav ul, nav li { margin: 0; list-style:none; list-style-image: none; }
small { font-size: 85%; }
strong, th { font-weight: bold; }
td, td img { vertical-align: top; }
sub { vertical-align: sub; font-size: smaller; }
sup { vertical-align: super; font-size: smaller; }
pre { padding: 15px; white-space: pre; white-space: pre-wrap; white-space: pre-line; word-wrap: break-word; }
textarea { overflow: auto; }
td { vertical-align: top; }
/* Set sub, sup without affecting line-height: gist.github.com/413930 */
sub, sup { font-size: 75%; line-height: 0; position: relative; }
sup { top: -0.5em; }
sub { bottom: -0.25em; }
pre {
/* www.pathf.com/blogs/2008/05/formatting-quoted-code-in-blog-posts-css21-white-space-pre-wrap/ */
white-space: pre; white-space: pre-wrap; word-wrap: break-word;
padding: 15px;
}
textarea { overflow: auto; } /* www.sitepoint.com/blogs/2010/08/20/ie-remove-textarea-scrollbars/ */
.ie6 legend, .ie7 legend { margin-left: -7px; }
/* Align checkboxes, radios, text inputs with their label by: Thierry Koblentz tjkdesign.com/ez-css/css/base.css */
input[type="radio"] { vertical-align: text-bottom; }
input[type="checkbox"] { vertical-align: bottom; }
.ie7 input[type="checkbox"] { vertical-align: baseline; }
.ie6 input { vertical-align: text-bottom; }
label, input[type=button], input[type=submit], button { cursor: pointer; }
/* Hand cursor on clickable input elements */
label, input[type="button"], input[type="submit"], input[type="image"], button { cursor: pointer; }
/* Webkit browsers add a 2px margin outside the chrome of form elements */
button, input, select, textarea { margin: 0; }
/* Colors for form validity */
input:valid, textarea:valid { }
input:invalid, textarea:invalid { border-radius: 1px; -moz-box-shadow: 0px 0px 5px red; -webkit-box-shadow: 0px 0px 5px red; box-shadow: 0px 0px 5px red; }
.no-boxshadow input:invalid,
.no-boxshadow textarea:invalid { background-color: #f0dddd; }
input:invalid, textarea:invalid {
border-radius: 1px; -moz-box-shadow: 0px 0px 5px red; -webkit-box-shadow: 0px 0px 5px red; box-shadow: 0px 0px 5px red;
}
.no-boxshadow input:invalid, .no-boxshadow textarea:invalid { background-color: #f0dddd; }
/* These selection declarations have to be separate
No text-shadow: twitter.com/miketaylr/status/12228805301
Also: hot pink! */
::-moz-selection{ background: #FF5E99; color:#fff; text-shadow: none; }
::selection { background:#FF5E99; color:#fff; text-shadow: none; }
a:link { -webkit-tap-highlight-color: #FF5E99; }
::selection { background:#FF5E99; color:#fff; text-shadow: none; }
/* j.mp/webkit-tap-highlight-color */
a:link { -webkit-tap-highlight-color: #FF5E99; }
/* Make buttons play nice in IE:
www.viget.com/inspire/styling-the-button-element-in-internet-explorer/ */
button { width: auto; overflow: visible; }
/* Bicubic resizing for non-native sized IMG:
code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/ */
.ie7 img { -ms-interpolation-mode: bicubic; }
.ir { display: block; text-indent: -999em; overflow: hidden; background-repeat: no-repeat; text-align: left; direction: ltr; }
.hidden { display: none; visibility: hidden; }
.visuallyhidden { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px, 1px, 1px, 1px); }
.invisible { visibility: hidden; }
.clearfix:before, .clearfix:after { content: "\0020"; display: block; height: 0; visibility: hidden; }
.clearfix:after { clear: both; }
.clearfix { zoom: 1; }
/**
* You might tweak these..
*/
body, select, input, textarea {
/* #444 looks better than black: twitter.com/H_FJ/statuses/11800719859 */
color: #444;
/* Set your base font here, to apply evenly */
/* font-family: Georgia, serif; */
}
/* Headers (h1, h2, etc) have no default font-size or margin; define those yourself */
h1, h2, h3, h4, h5, h6 { font-weight: bold; }
a, a:active, a:visited { color: #607890; }
a:hover { color: #036; }
/* Primary Styles
Author:
/**
* Primary styles
*
* Author:
*/
@@ -99,28 +181,78 @@ button { width: auto; overflow: visible; }
@media all and (orientation:portrait) {
/**
* Non-semantic helper classes: please define your styles before this section.
*/
/* For image replacement */
.ir { display: block; text-indent: -999em; overflow: hidden; background-repeat: no-repeat; text-align: left; direction: ltr; }
/* Hide for both screenreaders and browsers:
css-discuss.incutio.com/wiki/Screenreader_Visibility */
.hidden { display: none; visibility: hidden; }
/* Hide only visually, but have it available for screenreaders: by Jon Neal.
www.webaim.org/techniques/css/invisiblecontent/ & j.mp/visuallyhidden */
.visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
/* Extends the .visuallyhidden class to allow the element to be focusable when navigated to via the keyboard: drupal.org/node/897638 */
.visuallyhidden.focusable:active,
.visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; }
/* Hide visually and from screenreaders, but maintain layout */
.invisible { visibility: hidden; }
/* The Magnificent Clearfix: Updated to prevent margin-collapsing on child elements.
j.mp/bestclearfix */
.clearfix:before, .clearfix:after { content: "\0020"; display: block; height: 0; overflow: hidden; }
.clearfix:after { clear: both; }
/* Fix clearfix: blueprintcss.lighthouseapp.com/projects/15318/tickets/5-extra-margin-padding-bottom-of-page */
.clearfix { zoom: 1; }
/**
* Media queries for responsive design.
*
* These follow after primary styles so they will successfully override.
*/
@media all and (orientation:portrait) {
/* Style adjustments for portrait mode goes here */
}
@media all and (orientation:landscape) {
@media all and (orientation:landscape) {
/* Style adjustments for landscape mode goes here */
}
/* Grade-A Mobile Browsers (Opera Mobile, Mobile Safari, Android Chrome)
consider this: www.cloudfour.com/css-media-query-for-mobile-is-fools-gold/ */
@media screen and (max-device-width: 480px) {
/* Uncomment if you don't want iOS and WinMobile to mobile-optimize the text for you: j.mp/textsizeadjust */
/* html { -webkit-text-size-adjust:none; -ms-text-size-adjust:none; } */
}
/**
* Print styles.
*
* Inlined to avoid required HTTP connection: www.phpied.com/delay-loading-your-print-css/
*/
@media print {
* { background: transparent !important; color: #444 !important; text-shadow: none !important; }
* { background: transparent !important; color: black !important; text-shadow: none !important; filter:none !important;
-ms-filter: none !important; } /* Black prints faster: sanbeiji.com/archives/953 */
a, a:visited { color: #444 !important; text-decoration: underline; }
a:after { content: " (" attr(href) ")"; }
abbr:after { content: " (" attr(title) ")"; }
.ir a:after { content: ""; }
a[href]:after { content: " (" attr(href) ")"; }
abbr[title]:after { content: " (" attr(title) ")"; }
.ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } /* Don't show links for images, or javascript/internal links */
pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }
thead { display: table-header-group; }
thead { display: table-header-group; } /* css-discuss.incutio.com/wiki/Printing_Tables */
tr, img { page-break-inside: avoid; }
@page { margin: 0.5cm; }
p, h2, h3 { orphans: 3; widows: 3; }

View File

@@ -1,537 +0,0 @@
<!doctype html>
<!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -->
<!--[if lt IE 7 ]> <html lang="en" class="no-js ie6"> <![endif]-->
<!--[if IE 7 ]> <html lang="en" class="no-js ie7"> <![endif]-->
<!--[if IE 8 ]> <html lang="en" class="no-js ie8"> <![endif]-->
<!--[if IE 9 ]> <html lang="en" class="no-js ie9"> <![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--> <html lang="en" class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
Remove this if you use the .htaccess -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Element Consistency Tests</title>
<meta name="description" content="">
<meta name="author" content="">
<!-- Mobile viewport optimized: j.mp/bplateviewport -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Place favicon.ico & apple-touch-icon.png in the root of your domain and delete these references -->
<link rel="shortcut icon" href="/favicon.ico">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<!-- CSS : implied media="all" -->
<link rel="stylesheet" href="../css/style.css?v=2">
<!-- Uncomment if you are specifically targeting less enabled mobile browsers
<link rel="stylesheet" media="handheld" href="../css/handheld.css?v=2"> -->
<!-- All JavaScript at the bottom, except for Modernizr which enables HTML5 elements & feature detects -->
<script src="../js/libs/modernizr-1.6.min.js"></script>
</head>
<body>
<div id="container">
<header>
</header>
<div id="main">
<!-- demo content lovingly lifted from the azbuka project
http://code.google.com/p/azbuka/
and the bluetrip project
http://bluetrip.org/
and peter beverloo
http://peter.sh/examples/?/html/meter-progress.html
-->
<h1>Title 01 Heading</h1>
<hr />
<h2>Level 02 Heading</h2>
<p>Lorem ipsum <em>emphasised text</em> dolor sit amet, <strong>strong text</strong>
consectetur adipisicing elit, <abbr title="">abbreviated text</abbr> sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut
<q>quoted text</q> enim ad minim veniam, quis nostrud exercitation <a href="/">link text</a>
ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute
<ins>inserted text</ins> irure dolor in reprehenderit in voluptate velit esse cillum
dolore eu fugiat nulla pariatur. Excepteur sint occaecat <code>code text</code> cupidatat
non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>
Suspendisse rhoncus, est ac sollicitudin viverra, leo orci sagittis massa, sed condimentum <acronym title="">acronym text</acronym> est tortor a lectus. Curabitur porta feugiat ullamcorper. Integer lacinia mi id odio faucibus eget tincidunt nisl iaculis. Nam adipiscing hendrerit turpis, et porttitor felis sollicitudin et. Donec dictum massa ac neque accumsan tempor. Cras aliquam, ipsum sit amet laoreet hendrerit, purus <del>deleted text</del> sapien convallis dui, et porta leo ipsum ac nunc. Nullam ornare porta dui ac semper. Cras aliquam laoreet hendrerit. Quisque vulputate dolor eget mi porta vel porta nisl pretium. Vivamus non leo magna, quis imperdiet risus. Morbi tempor risus placerat tellus imperdiet fringilla.
</p>
<blockquote>
<p>I am not one who was born in the possession of knowledge; I am one who is fond of antiquity, and earnest in seeking it there.</p>
</blockquote>
<p><cite><a href="/">Confucius, The Confucian Analects</a></cite>, (551 BC - 479 BC)</p>
<h3>Level 03 Heading</h3>
<p>Extended paragraph. <a href="">Lorem ipsum</a> dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<ol>
<li>Unus</li>
<li>Duo</li>
<li>Tres</li>
<li>Quattuor</li>
</ol>
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.</p>
<h3>Header 3</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.</p>
<h4>Unordered lists</h4>
<ul>
<li>Lorem ipsum dolor sit amet</li>
<li>Consectetur adipisicing elit</li>
<li>Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua</li>
<li>Ut enim ad minim veniam</li>
</ul>
<p>Lorem ipsum dolor sit amet,consectetur adipisicing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.</p>
<pre><code>body { font:0.8125em/1.618 Arial, sans-serif;
background-color:#fff;
color:#111;
}</code></pre>
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.</p>
<h4>Header 4</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.</p>
<dl>
<dt>Definition list</dt>
<dd>Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat.</dd>
<dt>Lorem ipsum dolor sit amet</dt>
<dd>Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat.</dd>
</dl>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.</p>
<h4>Ordered list</h4>
<ol>
<li>List item</li>
<li>List item</li>
<li>List item
<ol>
<li>List item level 2</li>
<li>List item level 2
<ol>
<li>List item level 3</li>
<li>List item level 3</li>
</ol>
</li>
</ol>
</li>
</ol>
<h4>Unordered list</h4>
<ul>
<li>List item 01</li>
<li>List item 02</li>
<li>List item 03
<ul>
<li>List item level 2</li>
<li>List item level 2
<ul>
<li>List item level 3</li>
<li>List item level 3</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.</p>
<h4>Tables</h4>
<table summary="Jimi Hendrix albums">
<caption>Jimi Hendrix - albums</caption>
<thead>
<tr>
<th>Album</th>
<th>Year</th>
<th>Price</th>
</tr>
</thead>
<tfoot>
<tr>
<td>Album</td>
<td>Year</td>
<td>Price</td>
</tr>
</tfoot>
<tbody>
<tr>
<td>Are You Experienced </td>
<td>1967</td>
<td>$10.00</td>
</tr>
<tr>
<td>Axis: Bold as Love</td>
<td>1967</td>
<td>$12.00</td>
</tr>
<tr>
<td>Electric Ladyland</td>
<td>1968</td>
<td>$10.00</td>
</tr>
<tr>
<td>Band of Gypsys</td>
<td>1970</td>
<td>$12.00</td>
</tr>
<tbody>
</table>
<p>
I am <a href="http://devkick.com/lab/tripoli/sample.php?abc123">the a tag</a> example<br>
I am <abbr title="test">the abbr tag</abbr> example<br>
I am <acronym>the acronym tag</acronym> example<br>
I am <b>the b tag</b> example<br>
I am <big>the big tag</big> example<br>
I am <cite>the cite tag</cite> example<br>
I am <code>the code tag</code> example<br>
I am <del>the del tag</del> example<br>
I am <dfn>the dfn tag</dfn> example<br>
I am <em>the em tag</em> example<br>
I am <font face="verdana">the font tag</font> example<br>
I am <i>the i tag</i> example<br>
I am <ins>the ins tag</ins> example<br>
I am <kbd>the kbd tag</kbd> example<br>
I am <q>the q tag <q>inside</q> a q tag</q> example<br>
I am <s>the s tag</s> example<br>
I am <samp>the samp tag</samp> example<br>
I am <small>the small tag</small> example<br>
I am <span>the span tag</span> example<br>
I am <strike>the strike tag</strike> example<br>
I am <strong>the strong tag</strong> example<br>
I am <sub>the sub tag</sub> example<br>
I am <sup>the sup tag</sup> example<br>
I am <tt>the tt tag</tt> example<br>
I am <var>the var tag</var> example<br>
I am <u>the u tag</u> example
</p>
<p>This is a &lt;p&gt; with some <code>code</code> inside.</p>
<h3>What is Lorem Ipsum?</h3>
<p><b>Lorem Ipsum</b> is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<p><strong>This</strong> Lorem Ipsum HTML example is created from the parts of Placeholder Markup with Lorem Ipsum - Jon Tan,
Emastic CSS Framework,
Tripoli CSS Framework and
Baseline CSS Framework .</p>
<address>Address: somewhere, World</address>
<p>
<a href="#">Link</a><br>
<strong>&lt;strong&gt;</strong><br>
<del>&lt;del&gt; deleted</del><br>
<dfn>&lt;dfn&gt; dfn</dfn><br>
<em>&lt;em&gt; emphasis</em>
</p>
<pre>
<code>&lt;html&gt;</code>
<code>&lt;head&gt;</code>
<code>&lt;/head&gt;</code>
<code>&lt;body&gt;</code>
<code>&lt;div class = "main"&gt; &lt;div&gt;</code>
<code>&lt;/body&gt;</code>
<code>&lt;/html&gt; </code>
</pre>
<tt>&lt;tt&gt;
Pellentesque tempor, dui ut ultrices viverra, neque urna blandit nisi, id accumsan dolor est vitae risus.
</tt>
<hr>
<!-- this following markup from http://bluetrip.org/ -->
<dl>
<dt>Description list title 01</dt>
<dd>Description list description 01</dd>
<dt>Description list title 02</dt>
<dd>Description list description 02</dd>
<dd>Description list description 03</dd>
</dl>
<table>
<caption>Table Caption</caption>
<thead>
<tr>
<th>Table head th</th>
<td>Table head td</td>
</tr>
</thead>
<tfoot>
<tr>
<th>Table foot th</th>
<td>Table foot td</td>
</tr>
</tfoot>
<tbody>
<tr>
<th>Table body th</th>
<td>Table body td</td>
</tr>
<tr>
<td>Table body td</td>
<td>Table body td</td>
</tr>
</tbody>
</table>
<hr>
<form action="#">
<fieldset>
<legend>Form legend</legend>
<div><label for="f1">Optional Text input:</label><input type="text" id="f1" value="input text" /></div>
<div><label for="rt1">Required Text input:</label><input type="text" id="rt1" required /></div>
<div><label for="twp1">Text input with pattern requirement and placeholder:</label><input type="text" pattern="\d{5}(-\d{4})?" title="a US Zip code, with or without the +4 exension" placeholder="12345-6789"/></div>
<div><label for="s1">Search input:</label><input type="search" id="s1" /></div>
<div><label for="e1">Email input:</label><input type="email" id="e1" /></div>
<div><label for="u1">URL input:</label><input type="url" id="u1" /></div>
<div><label for="pw">Password input:</label><input type="password" id="pw" value="password" /></div>
<div><label for="f2">Radio input:</label><input type="radio" id="f2" /></div>
<div><label for="f3">Checkbox input:</label><input type="checkbox" id="f3" /></div>
<div><label for="f4">Select field:</label><select id="f4"><option>Option 01</option><option>Option 02</option></select></div>
<div><label for="f5">Textarea:</label><textarea id="f5" cols="30" rows="5" >Textarea text</textarea></div>
<div><label for="f6">Input Button:</label> <input type="button" id="f6" value="button text" /></div>
<div><label for="f7">Submit Button:</label> <input type="submit" id="f7" value="button text" /></div>
</fieldset>
</form>
<!-- thx peter beverloo: http://peter.sh/examples/?/html/meter-progress.html -->
<p id="no-support" style="color: red; margin-bottom: 12px;">
Your browser does not support these elements yet! Consider downloading a <a href="http://tools.peter.sh/download-latest-chromium.php">Chromium Nightly</a>.<br />
</p>
<h3>&lt;progress&gt;</h3>
<p>
The progress element (spec: <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#the-progress-element">4.10.16</a>) represents the completion progress of a task and can be both indeterminate as determinate.
</p>
<ul class="compact">
<li>
<label>Indeterminate</label>
<progress max="100"></progress>
</li>
<li>
<label>Progress: 0%</label>
<progress max="10" value="0"></progress>
</li>
<li>
<label>Progress: 100%</label>
<progress max="3254" value="3254"></progress>
</li>
<li>
<label>Progress: 57%</label>
<progress max="0.7" value="0.4"></progress>
</li>
<li>
<label>Javascript</label>
<progress id="progress-javascript-example"></progress>
</li>
</ul>
<h3>&lt;meter&gt;</h3>
<p>
Displaying a scalar measurement within a known range, like hard drive usage, can be done using the meter element (spec: <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html#the-meter-element">4.10.17</a>)
</p>
<ul class="compact">
<li>
<label>Meter: empty</label>
<meter value="0"></meter>
</li>
<li>
<label>Meter: full</label>
<meter value="1"></meter>
</li>
<li>
<label>Meter: "a bit"</label>
<meter min=".34" max=".41" value=".36"></meter>
</li>
<li>
<label>Preferred usage</label>
<meter min="50" max="250" low="100" high="200" value="120"></meter>
</li>
<li>
<label>Too much traffic</label>
<meter min="1024" max="10240" low="2048" high="8192" value="9216"></meter>
</li>
<li>
<label>Optimum value</label>
<meter value=".5" optimum=".8"></meter>
</li>
<li>
<label>Javascript</label>
<meter id="meter-javascript-example" value="0"></progress>
</li>
</ul>
<script>
(function () {
if (! ('position' in document.createElement ('progress'))) {
var elements = document.querySelectorAll ('meter, progress');
for (var i = 0, j = elements.length; i < j; i++) {
elements [i].style.border = "1px solid red";
elements [i].style.height = "12px";
elements [i].style.display = "inline-block";
elements [i].style.webkitAppearance = "none";
}
return ;
}
document.getElementById ('no-support').style.display = 'none';
/** Setup the <progress> JavaScript example **/
var progressExample = document.getElementById ('progress-javascript-example');
progressExample.min = 50;
progressExample.max = 122;
setInterval (function ()
{
progressExample.value = progressExample.min + Math.random () * (progressExample.max - progressExample.min);
}, 1000);
/** We'd like some fancy <meter> examples too **/
var meterExample = document.getElementById ('meter-javascript-example');
meterExample.min = 0;
meterExample.max = 100;
meterExample.value = 50;
meterExample.low = 20;
meterExample.high = 80;
meterExample.optimum = 65;
setInterval (function ()
{
meterExample.value = meterExample.min + Math.random () * (meterExample.max - meterExample.min);
meterExample.optimum = 65 + (5 - Math.random () * 10);
}, 1000);
})();
</script>
</div>
<footer>
</footer>
</div> <!--! end of #container -->
<!-- Javascript at the bottom for fast page loading -->
<!-- Grab Google CDN's jQuery. fall back to local if necessary -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
<script>!window.jQuery && document.write(unescape('%3Cscript src="../js/libs/jquery-1.4.2.js"%3E%3C/script%3E'))</script>
<!-- scripts concatenated and minified via ant build script-->
<script src="../js/plugins.js"></script>
<script src="../js/script.js"></script>
<!-- end concatenated and minified scripts-->
<!--[if lt IE 7 ]>
<script src="../js/libs/dd_belatedpng.js"></script>
<script> DD_belatedPNG.fix('img, .png_bg'); //fix any <img> or .png_bg background-images </script>
<![endif]-->
<!-- yui profiler and profileviewer - remove for production -->
<script src="../js/profiling/yahoo-profiling.min.js"></script>
<script src="../js/profiling/config.js"></script>
<!-- end profiling code -->
<!-- asynchronous google analytics: mathiasbynens.be/notes/async-analytics-snippet
change the UA-XXXXX-X to be your site's ID -->
<script>
var _gaq = [['_setAccount', 'UA-XXXXX-X'], ['_trackPageview']];
(function(d, t) {
var g = d.createElement(t),
s = d.getElementsByTagName(t)[0];
g.async = true;
g.src = ('https:' == location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
s.parentNode.insertBefore(g, s);
})(document, 'script');
</script>
</body>
</html>

View File

@@ -1,85 +0,0 @@
/*
style.css contains a reset, font normalization and some base styles.
credit is left where credit is due.
additionally, much inspiration was taken from these projects:
yui.yahooapis.com/2.8.1/build/base/base.css
camendesign.com/design/
praegnanz.de/weblog/htmlcssjs-kickstart
*/
/*
html5doctor.com Reset Stylesheet (Eric Meyer's Reset Reloaded + HTML5 baseline)
v1.4 2009-07-27 | Authors: Eric Meyer & Richard Clark
html5doctor.com/html-5-reset-stylesheet/
*/
html, body, div, span, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
abbr, address, cite, code,
del, dfn, em, img, ins, kbd, q, samp,
small, strong, sub, sup, var,
b, i,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, figcaption, figure,
footer, header, hgroup, menu, nav, section, summary,
time, mark, audio, video {
margin:0;
padding:0;
border:0;
outline:0;
font-size:100%;
vertical-align:baseline;
background:transparent;
}
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display:block;
}
nav ul { list-style:none; }
blockquote, q { quotes:none; }
blockquote:before, blockquote:after,
q:before, q:after { content:''; content:none; }
a { margin:0; padding:0; font-size:100%; vertical-align:baseline; background:transparent; }
ins { background-color:#ff9; color:#000; text-decoration:none; }
mark { background-color:#ff9; color:#000; font-style:italic; font-weight:bold; }
del { text-decoration: line-through; }
abbr[title], dfn[title] { border-bottom:1px dotted; cursor:help; }
/* tables still need cellspacing="0" in the markup */
table { border-collapse:collapse; border-spacing:0; }
hr { display:block; height:1px; border:0; border-top:1px solid #ccc; margin:1em 0; padding:0; }
input, select { vertical-align:middle; }
/* END RESET CSS */
/* fonts.css from the YUI Library: developer.yahoo.com/yui/
Please refer to developer.yahoo.com/yui/fonts/ for font sizing percentages
There are three custom edits:
* remove arial, helvetica from explicit font stack
* we normalize monospace styles ourselves
* table font-size is reset in the HTML5 reset above so there is no need to repeat
*/
body { font:13px/1.231 sans-serif; *font-size:small; } /* hack retained to preserve specificity */
select, input, textarea, button { font:99% sans-serif; }
/* normalize monospace sizing
* en.wikipedia.org/wiki/MediaWiki_talk:Common.css/Archive_11#Teletype_style_fix_for_Chrome
*/
pre, code, kbd, samp { font-family: monospace, sans-serif; }

View File

@@ -1,41 +0,0 @@
body { font:13px/1.231 sans-serif; *font-size:small; } /* hack retained to preserve specificity */
body, select, input, textarea {
/* #444 looks better than black: twitter.com/H_FJ/statuses/11800719859 */
color: #444;
/* set your base font here, to apply evenly
/* font-family: Georgia, serif; */
}
/* Headers (h1,h2,etc) have no default font-size or margin,
you'll want to define those yourself. */
h1,h2,h3,h4,h5,h6 { font-weight: bold; }
h1 { font-size: 2em; }
select, input, textarea, button { font:99% sans-serif; }
/* Accessible focus treatment: people.opera.com/patrickl/experiments/keyboard/test */
a:hover, a:active { outline: none; }
.current { background: #ccc; }
header span { padding: 0.2em 0.5em; display: inline-block; }
dd, h1, body, html { margin: 0;}
a, a:active, a:visited { color: #607890; }
a:hover { color: #036; }
.wrapper {width:200px; border:1px solid red;}
dl {margin:0 auto; width:900px;}
dt {background-color:#ccc; margin-bottom:20px; cursor:pointer; cursor:hand; padding:5px; font-weight:bold; }
dd {margin-bottom:30px;}
#clear-demo {width:500px; border:1px solid black;}
#clear-demo-l {width:200px; border:1px solid black; float:left;}
#clear-demo-r {width:200px; border:1px solid black; float:right;}
#clear-demo-b {width:200px; border:1px solid black;}
header {text-align:center;}
.show, .hide {color: #607890; cursor:pointer; cursor:hand;}
body {
padding-bottom: 200px;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 674 B

View File

@@ -1,312 +0,0 @@
<!doctype html>
<!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -->
<!--[if lt IE 7 ]> <html lang="en" class="no-js ie6"> <![endif]-->
<!--[if IE 7 ]> <html lang="en" class="no-js ie7"> <![endif]-->
<!--[if IE 8 ]> <html lang="en" class="no-js ie8"> <![endif]-->
<!--[if IE 9 ]> <html lang="en" class="no-js ie9"> <![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--> <html lang="en" class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
Remove this if you use the .htaccess -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Boilerplate Test Suite</title>
<meta name="description" content="">
<meta name="author" content="">
<!-- Mobile viewport optimized: j.mp/bplateviewport -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Place favicon.ico & apple-touch-icon.png in the root of your domain and delete these references -->
<link rel="shortcut icon" href="/favicon.ico">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<!-- CSS : implied media="all" -->
<link rel="stylesheet" href="../css/style.css?v=2">
<link rel="stylesheet" href="hack2.css">
<!-- Uncomment if you are specifically targeting less enabled mobile browsers
<link rel="stylesheet" media="handheld" href="../css/handheld.css?v=2"> -->
<!-- All JavaScript at the bottom, except for Modernizr which enables HTML5 elements & feature detects -->
<script src="../js/libs/modernizr-1.6.min.js"></script>
</head>
<body>
<div id="container">
<header>
<br /><br /><h1>HTML5 Boilerplate CSS Hack Sheet</h1><br /><br />
</header>
<div id="main" style="display:block;">
<dl>
<dt>Hack 01 - Set default color</dt>
<dd>
HTML5 Boilerplate suggests the default color looks better when set to #444 instead of #000.<br />
<span style="color:black;">Web font default color</span>
</dd>
<dt>Hack 02 - Vertical Scroll Bar</dt>
<dd>
Click <a href="#" id="shorten">contract</a> | <a href="#" id="expand">expand</a> to see how Boilerplate forces a scrollbar in non-IE.
</dd>
<dt>Hack 03 - Accessible focus style</dt>
<dd>
Remove dotted outline around 'a' element on hover and on focus in certain browsers
<br /><br />
<span href="#" class="show">With Boilerplate CSS</span> | <span href="#" class="hide">Without Boilerplate CSS</span>
<br /><br />
<a href="#" class="preventDefault">Click me</a>
</dd>
<dt>Hack 04 - Pre Wrapping</dt>
<dd>
Default <code>pre</code> doesn't wrap text. Boilerplate forces <code>pre</code> to wrap text.
<br /><br />
<span href="#" class="show">With Boilerplate CSS</span> | <span href="#" class="hide">Without Boilerplate CSS</span>
<br /><br />
with wrapping:<br /><br />
<div style="height:115px;">
<div class="wrapper">
<pre>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</pre>
</div>
</div><br />
without wrapping:<br /><br />
<div class="wrapper">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</div>
</dd>
<dt>Hack 05 - Remove default textarea scrollbar in IE</dt>
<dd>
IE shows a disabled scrollbar on empty <code>textarea</code>.<br><br>
<span href="#" class="show">With Boilerplate CSS</span> | <span href="#" class="hide">Without Boilerplate CSS</span>
<br /><br />
<form>
<textarea></textarea>
</form>
</dd>
<dt>Hack 06 - IE6,7 legend margin</dt>
<dd>
Left align form legend to the inner text in IE 6,7.<br /><br />
<span href="#" class="show">With Boilerplate CSS</span> | <span href="#" class="hide">Without Boilerplate CSS</span>
<br /><br />
<form>
<fieldset>
<legend>Information:</legend><br />
Name: <input type="text" size="30" /><br />
Email: <input type="text" size="30" /><br />
Date of birth: <input type="text" size="10" />
</fieldset>
</form>
</dd>
<dt>Hack 07 - Vertically align checkboxes, radios, text inputs with their label</dt>
<dd>
<span href="#" class="show">With Boilerplate CSS</span> | <span href="#" class="hide">Without Boilerplate CSS</span>
<br /><br />
<input type="radio" /> Option A <br /><br />
<input type="checkbox" /> Item B <br /><br />
Name: <input type="text" />
</dd>
<dt>Hack 08 - Hand cursor on clickable input elements</dt>
<dd>
<span href="#" class="show">With Boilerplate CSS</span> | <span href="#" class="hide">Without Boilerplate CSS</span>
<br /><br />
Input with type submit <input type="submit" value="submit" />
</dd>
<dt>Hack 09 - Webkit browsers form elements margin</dt>
<dd>
Webkit browsers add a 2px margin outside the chrome of form elements.<br /><br />
<span href="#" class="show">With Boilerplate CSS</span> | <span href="#" class="hide">Without Boilerplate CSS</span>
<br /><br />
<form>
<input type="submit" value="submit" /><br /><br />
<button type="button">Click Me!</button><br /><br />
<select><option>Default</option></select>
</form>
</dd>
<dt>Hack 10 - Make buttons width rendered correctly</dt>
<dd>
IE adds extra padding to <code>button</code>. This fixes the issue. <br /><br />
<span href="#" class="show">With Boilerplate CSS</span> | <span href="#" class="hide">Without Boilerplate CSS</span>
<br /><br />
<form>
<button type="button">Click Me!</button>
<button type="button">This is a really long button</button>
</form>
</dd>
<dt>Hack 11 - Bicubic resizing for non-native sized IMG</dt>
<dd>
IE7 hack to reduce distortion caused by image resizing <br /><br />
<span href="#" class="show">With Boilerplate CSS</span> | <span href="#" class="hide">Without Boilerplate CSS</span>
<br /><br />
<img src="../apple-touch-icon.png" width="27" /><br />
<img src="../apple-touch-icon.png" width="57" /><br />
<img src="../apple-touch-icon.png" width="157" /><br />
</dd>
<dt>Hack 12 - Hide visually</dt>
<dd>
Hide elements visually, but have it available for screen readers.
<br /><br />
<span href="#" class="show">With Boilerplate CSS</span> | <span href="#" class="hide">Without Boilerplate CSS</span>
<br /><br />
<div class="visuallyhidden">showing</div>
</dd>
<dt>Hack 13 - Image text replacement</dt>
<dd>
Replace text with images.
<br /><br />
<span href="#" class="show">With Boilerplate CSS</span> | <span href="#" class="hide">Without Boilerplate CSS</span>
<br /><br />
<div class="ir" style="background:url('../apple-touch-icon.png'); width:57px; height:57px;">Apple Touch Icon</div>
</dd>
<dt>Hack 14 - Clear Floats</dt>
<dd>
Clear Floated elements without extra markup.
<br /><br />
<span href="#" class="show">With Boilerplate CSS</span> | <span href="#" class="hide">Without Boilerplate CSS</span>
<br /><br />
<div id="clear-demo" class="clearfix">
<div id="clear-demo-l">text floated left</div><div id="clear-demo-r">text floated right</div>
</div>
<div id="clear-demo-b">unfloated text</div>
</dd>
<dt>Hack 15 - PNG fix</dt>
<dd>fix pngs for correct display in IE6
<br /> <br />
<div style="position:relative">
<!-- wassup gradient. -->
<div style="position:absolute; height: 40px; background-color: #444444; background-image: -moz-linear-gradient(top, #444444, #999999); background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #444444),color-stop(1, #999999)); filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#444444', EndColorStr='#999999'); ">
<div class="png_bg" style="border:1px solid #ddd; width:100px; padding:10px 10px 10px 50px; display:inline-block; background:url(test_tubes.png) no-repeat 5px center;">
<img src="internet_explorer.png" alt="IE is so awesome" />
</div>
</div>
</dd>
</dl>
</div>
<footer>
</footer>
</div> <!--! end of #container -->
<!-- Javascript at the bottom for fast page loading -->
<!-- Grab Google CDN's jQuery. fall back to local if necessary -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
<script>!window.jQuery && document.write(unescape('%3Cscript src="../js/libs/jquery-1.4.2.js"%3E%3C/script%3E'))</script>
<script>
$('#expand').click(function() {
$('#container').css('height','auto').css('overflow','');
return false;
});
$('#shorten').click(function() {
$('#container').css('height','300px').css('overflow','hidden');
return false;
});
$('#atag').click(function() {
return false;
});
$('.show').click(function(){
$('.show').addClass('current')
$('.hide').removeClass('current');
showStyle();
return false;
});
$('.hide').click(function(){
$('.hide').addClass('current')
$('.show').removeClass('current');
// freeze the size of each tests so the page doesnt jump.
$('dd').each(function(){
$(this).height( $(this).height() );
});
hideStyle();
return false;
});
var linkTags = $('link');
function hideStyle() {
// tee hee
$('link[href*=style.css]').attr('media','braille');
}
function showStyle() {
$('link[href*=style.css]').attr('media','all');
}
$('.preventDefault').click(function() {
return false;
});
$(function(){
$('.show').addClass('current');
})
</script>
<!-- scripts concatenated and minified via ant build script-->
<script src="../js/plugins.js"></script>
<script src="../js/script.js"></script>
<!-- end concatenated and minified scripts-->
<!--[if lt IE 7 ]>
<script src="../js/libs/dd_belatedpng.js"></script>
<script> DD_belatedPNG.fix('img, .png_bg'); //fix any <img> or .png_bg background-images </script>
<![endif]-->
<!-- yui profiler and profileviewer - remove for production -->
<script src="../js/profiling/yahoo-profiling.min.js"></script>
<script src="../js/profiling/config.js"></script>
<!-- end profiling code -->
<!-- asynchronous google analytics: mathiasbynens.be/notes/async-analytics-snippet
change the UA-XXXXX-X to be your site's ID -->
<script>
var _gaq = [['_setAccount', 'UA-XXXXX-X'], ['_trackPageview']];
(function(d, t) {
var g = d.createElement(t),
s = d.getElementsByTagName(t)[0];
g.async = true;
g.src = ('https:' == location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
s.parentNode.insertBefore(g, s);
})(document, 'script');
</script>
</body>
</html>

43
humans.txt Normal file
View File

@@ -0,0 +1,43 @@
/* the humans responsible & colophon */
/* humanstxt.org */
/* TEAM */
<your title>: <your name>
Site:
Twitter:
Location:
/* THANKS */
Names (& URL):
/* SITE */
Standards: HTML5, CSS3
Components: Modernizr, jQuery
Software:
-o/-
+oo//-
:ooo+//:
-ooooo///-
/oooooo//:
:ooooooo+//-
-+oooooooo///-
-://////////////+oooooooooo++////////////::
:+ooooooooooooooooooooooooooooooooooooo+:::-
-/+ooooooooooooooooooooooooooooooo+/::////:-
-:+oooooooooooooooooooooooooooo/::///////:-
--/+ooooooooooooooooooooo+::://////:-
-:+ooooooooooooooooo+:://////:--
/ooooooooooooooooo+//////:-
-ooooooooooooooooooo////-
/ooooooooo+oooooooooo//:
:ooooooo+/::/+oooooooo+//-
-oooooo/::///////+oooooo///-
/ooo+::://////:---:/+oooo//:
-o+/::///////:- -:/+o+//-
:-:///////:- -:/://
-////:- --//:
-- -:

View File

@@ -1,3 +1,2 @@
*
!.gitignore

View File

@@ -1,24 +1,36 @@
<!doctype html>
<!--[if lt IE 7 ]> <html lang="en" class="no-js ie6"> <![endif]-->
<!--[if IE 7 ]> <html lang="en" class="no-js ie7"> <![endif]-->
<!--[if IE 8 ]> <html lang="en" class="no-js ie8"> <![endif]-->
<!--[if IE 9 ]> <html lang="en" class="no-js ie9"> <![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--> <html lang="en" class="no-js"> <!--<![endif]-->
<!doctype html>
<!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -->
<!--[if lt IE 7 ]> <html class="no-js ie6" lang="en"> <![endif]-->
<!--[if IE 7 ]> <html class="no-js ie7" lang="en"> <![endif]-->
<!--[if IE 8 ]> <html class="no-js ie8" lang="en"> <![endif]-->
<!--[if (gte IE 9)|!(IE)]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
Remove this if you use the .htaccess -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="">
<meta name="author" content="">
<!-- Mobile viewport optimized: j.mp/bplateviewport -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Place favicon.ico & apple-touch-icon.png in the root of your domain and delete these references -->
<link rel="shortcut icon" href="/favicon.ico">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<!-- CSS: implied media="all" -->
<link rel="stylesheet" href="css/style.css?v=2">
<script src="js/libs/modernizr-1.6.min.js"></script>
<!-- Uncomment if you are specifically targeting less enabled mobile browsers
<link rel="stylesheet" media="handheld" href="css/handheld.css?v=2"> -->
<!-- All JavaScript at the bottom, except for Modernizr which enables HTML5 elements & feature detects -->
<script src="js/libs/modernizr-1.7.min.js"></script>
</head>
@@ -28,49 +40,41 @@
<header>
</header>
<div id="main">
<div id="main" role="main">
</div>
<footer>
</footer>
</div> <!-- end of #container -->
</div> <!--! end of #container -->
<!-- JavaScript at the bottom for fast page loading -->
<!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if necessary -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.5.1.min.js">\x3C/script>')</script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
<script>!window.jQuery && document.write(unescape('%3Cscript src="js/libs/jquery-1.4.2.js"%3E%3C/script%3E'))</script>
<!-- scripts concatenated and minified via ant build script-->
<script src="js/plugins.js"></script>
<script src="js/script.js"></script>
<!-- end concatenated and minified scripts-->
<!-- end scripts-->
<!--[if lt IE 7 ]>
<script src="js/libs/dd_belatedpng.js"></script>
<script> DD_belatedPNG.fix('img, .png_bg'); </script>
<script>DD_belatedPNG.fix('img, .png_bg'); // Fix any <img> or .png_bg bg-images. Also, please read goo.gl/mZiyb </script>
<![endif]-->
<!-- yui profiler and profileviewer - remove for production -->
<script src="js/profiling/yahoo-profiling.min.js"></script>
<script src="js/profiling/config.js"></script>
<!-- end profiling code -->
<!-- change the UA-XXXXX-X to be your site's ID -->
<!-- mathiasbynens.be/notes/async-analytics-snippet Change UA-XXXXX-X to be your site's ID -->
<script>
var _gaq = [['_setAccount', 'UA-XXXXX-X'], ['_trackPageview']];
(function(d, t) {
var g = d.createElement(t),
s = d.getElementsByTagName(t)[0];
g.async = true;
g.src = ('https:' == location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
s.parentNode.insertBefore(g, s);
})(document, 'script');
var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.async=1;
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
s.parentNode.insertBefore(g,s)}(document,'script'));
</script>
</body>
</html>

View File

@@ -1,154 +0,0 @@
/*!
* jQuery JavaScript Library v1.4.2
* http://jquery.com/
*
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* Includes Sizzle.js
* http://sizzlejs.com/
* Copyright 2010, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
*
* Date: Sat Feb 13 22:33:48 2010 -0500
*/
(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);

File diff suppressed because it is too large Load Diff

16
js/libs/jquery-1.5.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,30 +0,0 @@
/*
* Modernizr v1.6
* http://www.modernizr.com
*
* Developed by:
* - Faruk Ates http://farukat.es/
* - Paul Irish http://paulirish.com/
*
* Copyright (c) 2009-2010
* Dual-licensed under the BSD or MIT licenses.
* http://www.modernizr.com/license/
*/
window.Modernizr=function(i,e,u){function s(a,b){return(""+a).indexOf(b)!==-1}function D(a,b){for(var c in a)if(j[a[c]]!==u&&(!b||b(a[c],E)))return true}function n(a,b){var c=a.charAt(0).toUpperCase()+a.substr(1);c=(a+" "+F.join(c+" ")+c).split(" ");return!!D(c,b)}function S(){f.input=function(a){for(var b=0,c=a.length;b<c;b++)L[a[b]]=!!(a[b]in h);return L}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" "));f.inputtypes=function(a){for(var b=0,c,k=a.length;b<
k;b++){h.setAttribute("type",a[b]);if(c=h.type!=="text"){h.value=M;if(/^range$/.test(h.type)&&h.style.WebkitAppearance!==u){l.appendChild(h);c=e.defaultView;c=c.getComputedStyle&&c.getComputedStyle(h,null).WebkitAppearance!=="textfield"&&h.offsetHeight!==0;l.removeChild(h)}else/^(search|tel)$/.test(h.type)||(c=/^(url|email)$/.test(h.type)?h.checkValidity&&h.checkValidity()===false:h.value!=M)}N[a[b]]=!!c}return N}("search tel url email datetime date month week time datetime-local number range color".split(" "))}
var f={},l=e.documentElement,E=e.createElement("modernizr"),j=E.style,h=e.createElement("input"),M=":)",O=Object.prototype.toString,q=" -webkit- -moz- -o- -ms- -khtml- ".split(" "),F="Webkit Moz O ms Khtml".split(" "),v={svg:"http://www.w3.org/2000/svg"},d={},N={},L={},P=[],w,Q=function(a){var b=document.createElement("style"),c=e.createElement("div");b.textContent=a+"{#modernizr{height:3px}}";(e.head||e.getElementsByTagName("head")[0]).appendChild(b);c.id="modernizr";l.appendChild(c);a=c.offsetHeight===
3;b.parentNode.removeChild(b);c.parentNode.removeChild(c);return!!a},o=function(){var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return function(b,c){c=c||document.createElement(a[b]||"div");b="on"+b;var k=b in c;if(!k){c.setAttribute||(c=document.createElement("div"));if(c.setAttribute&&c.removeAttribute){c.setAttribute(b,"");k=typeof c[b]=="function";if(typeof c[b]!="undefined")c[b]=u;c.removeAttribute(b)}}return k}}(),G={}.hasOwnProperty,R;R=
typeof G!=="undefined"&&typeof G.call!=="undefined"?function(a,b){return G.call(a,b)}:function(a,b){return b in a&&typeof a.constructor.prototype[b]==="undefined"};d.flexbox=function(){var a=e.createElement("div"),b=e.createElement("div");(function(k,g,r,x){g+=":";k.style.cssText=(g+q.join(r+";"+g)).slice(0,-g.length)+(x||"")})(a,"display","box","width:42px;padding:0;");b.style.cssText=q.join("box-flex:1;")+"width:10px;";a.appendChild(b);l.appendChild(a);var c=b.offsetWidth===42;a.removeChild(b);
l.removeChild(a);return c};d.canvas=function(){var a=e.createElement("canvas");return!!(a.getContext&&a.getContext("2d"))};d.canvastext=function(){return!!(f.canvas&&typeof e.createElement("canvas").getContext("2d").fillText=="function")};d.webgl=function(){var a=e.createElement("canvas");try{if(a.getContext("webgl"))return true}catch(b){}try{if(a.getContext("experimental-webgl"))return true}catch(c){}return false};d.touch=function(){return"ontouchstart"in i||Q("@media ("+q.join("touch-enabled),(")+
"modernizr)")};d.geolocation=function(){return!!navigator.geolocation};d.postmessage=function(){return!!i.postMessage};d.websqldatabase=function(){return!!i.openDatabase};d.indexedDB=function(){for(var a=-1,b=F.length;++a<b;){var c=F[a].toLowerCase();if(i[c+"_indexedDB"]||i[c+"IndexedDB"])return true}return false};d.hashchange=function(){return o("hashchange",i)&&(document.documentMode===u||document.documentMode>7)};d.history=function(){return!!(i.history&&history.pushState)};d.draganddrop=function(){return o("drag")&&
o("dragstart")&&o("dragenter")&&o("dragover")&&o("dragleave")&&o("dragend")&&o("drop")};d.websockets=function(){return"WebSocket"in i};d.rgba=function(){j.cssText="background-color:rgba(150,255,150,.5)";return s(j.backgroundColor,"rgba")};d.hsla=function(){j.cssText="background-color:hsla(120,40%,100%,.5)";return s(j.backgroundColor,"rgba")||s(j.backgroundColor,"hsla")};d.multiplebgs=function(){j.cssText="background:url(//:),url(//:),red url(//:)";return/(url\s*\(.*?){3}/.test(j.background)};d.backgroundsize=
function(){return n("backgroundSize")};d.borderimage=function(){return n("borderImage")};d.borderradius=function(){return n("borderRadius","",function(a){return s(a,"orderRadius")})};d.boxshadow=function(){return n("boxShadow")};d.textshadow=function(){return e.createElement("div").style.textShadow===""};d.opacity=function(){var a=q.join("opacity:.5;")+"";j.cssText=a;return s(j.opacity,"0.5")};d.cssanimations=function(){return n("animationName")};d.csscolumns=function(){return n("columnCount")};d.cssgradients=
function(){var a=("background-image:"+q.join("gradient(linear,left top,right bottom,from(#9f9),to(white));background-image:")+q.join("linear-gradient(left top,#9f9, white);background-image:")).slice(0,-17);j.cssText=a;return s(j.backgroundImage,"gradient")};d.cssreflections=function(){return n("boxReflect")};d.csstransforms=function(){return!!D(["transformProperty","WebkitTransform","MozTransform","OTransform","msTransform"])};d.csstransforms3d=function(){var a=!!D(["perspectiveProperty","WebkitPerspective",
"MozPerspective","OPerspective","msPerspective"]);if(a)a=Q("@media ("+q.join("transform-3d),(")+"modernizr)");return a};d.csstransitions=function(){return n("transitionProperty")};d.fontface=function(){var a,b=e.head||e.getElementsByTagName("head")[0]||l,c=e.createElement("style"),k=e.implementation||{hasFeature:function(){return false}};c.type="text/css";b.insertBefore(c,b.firstChild);a=c.sheet||c.styleSheet;b=k.hasFeature("CSS2","")?function(g){if(!(a&&g))return false;var r=false;try{a.insertRule(g,
0);r=!/unknown/i.test(a.cssRules[0].cssText);a.deleteRule(a.cssRules.length-1)}catch(x){}return r}:function(g){if(!(a&&g))return false;a.cssText=g;return a.cssText.length!==0&&!/unknown/i.test(a.cssText)&&a.cssText.replace(/\r+|\n+/g,"").indexOf(g.split(" ")[0])===0};f._fontfaceready=function(g){g(f.fontface)};return b('@font-face { font-family: "font"; src: "font.ttf"; }')};d.video=function(){var a=e.createElement("video"),b=!!a.canPlayType;if(b){b=new Boolean(b);b.ogg=a.canPlayType('video/ogg; codecs="theora"');
b.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"')||a.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');b.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"')}return b};d.audio=function(){var a=e.createElement("audio"),b=!!a.canPlayType;if(b){b=new Boolean(b);b.ogg=a.canPlayType('audio/ogg; codecs="vorbis"');b.mp3=a.canPlayType("audio/mpeg;");b.wav=a.canPlayType('audio/wav; codecs="1"');b.m4a=a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")}return b};d.localstorage=function(){try{return"localStorage"in
i&&i.localStorage!==null}catch(a){return false}};d.sessionstorage=function(){try{return"sessionStorage"in i&&i.sessionStorage!==null}catch(a){return false}};d.webWorkers=function(){return!!i.Worker};d.applicationcache=function(){return!!i.applicationCache};d.svg=function(){return!!e.createElementNS&&!!e.createElementNS(v.svg,"svg").createSVGRect};d.inlinesvg=function(){var a=document.createElement("div");a.innerHTML="<svg/>";return(a.firstChild&&a.firstChild.namespaceURI)==v.svg};d.smil=function(){return!!e.createElementNS&&
/SVG/.test(O.call(e.createElementNS(v.svg,"animate")))};d.svgclippaths=function(){return!!e.createElementNS&&/SVG/.test(O.call(e.createElementNS(v.svg,"clipPath")))};for(var H in d)if(R(d,H)){w=H.toLowerCase();f[w]=d[H]();P.push((f[w]?"":"no-")+w)}f.input||S();f.crosswindowmessaging=f.postmessage;f.historymanagement=f.history;f.addTest=function(a,b){a=a.toLowerCase();if(!f[a]){b=!!b();l.className+=" "+(b?"":"no-")+a;f[a]=b;return f}};j.cssText="";E=h=null;i.attachEvent&&function(){var a=e.createElement("div");
a.innerHTML="<elem></elem>";return a.childNodes.length!==1}()&&function(a,b){function c(p){for(var m=-1;++m<r;)p.createElement(g[m])}function k(p,m){for(var I=p.length,t=-1,y,J=[];++t<I;){y=p[t];m=y.media||m;J.push(k(y.imports,m));J.push(y.cssText)}return J.join("")}var g="abbr|article|aside|audio|canvas|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video".split("|"),r=g.length,x=RegExp("<(/*)(abbr|article|aside|audio|canvas|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video)",
"gi"),T=RegExp("\\b(abbr|article|aside|audio|canvas|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video)\\b(?!.*[;}])","gi"),z=b.createDocumentFragment(),A=b.documentElement,K=A.firstChild,B=b.createElement("style"),C=b.createElement("body");B.media="all";c(b);c(z);a.attachEvent("onbeforeprint",function(){for(var p=-1;++p<r;)for(var m=b.getElementsByTagName(g[p]),I=m.length,t=-1;++t<I;)if(m[t].className.indexOf("iepp_")<0)m[t].className+=" iepp_"+
g[p];K.insertBefore(B,K.firstChild);B.styleSheet.cssText=k(b.styleSheets,"all").replace(T,".iepp_$1");z.appendChild(b.body);A.appendChild(C);C.innerHTML=z.firstChild.innerHTML.replace(x,"<$1bdo")});a.attachEvent("onafterprint",function(){C.innerHTML="";A.removeChild(C);K.removeChild(B);A.appendChild(z.firstChild)})}(this,document);f._enableHTML5=true;f._version="1.6";l.className=l.className.replace(/\bno-js\b/,"")+" js";l.className+=" "+P.join(" ");return f}(this,this.document);

2
js/libs/modernizr-1.7.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,2 @@
*
!.gitignore

View File

@@ -1,34 +1,15 @@
(function($){
})(this.jQuery);
// usage: log('inside coolFunc', this, arguments);
// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
window.log = function(){
log.history = log.history || [];
log.history = log.history || []; // store logs to an array for reference
log.history.push(arguments);
if(this.console){
console.log( Array.prototype.slice.call(arguments) );
}
arguments.callee = arguments.callee.caller;
if(this.console) console.log( Array.prototype.slice.call(arguments) );
};
(function(doc){
var write = doc.write;
doc.write = function(q){
log('document.write(): ',arguments);
if (/docwriteregexwhitelist/.test(q)) write.apply(doc,arguments);
};
})(document);
// make it safe to use console.log always
(function(b){function c(){}for(var d="assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn".split(","),a;a=d.pop();)b[a]=b[a]||c})(window.console=window.console||{});
// place any jQuery/helper plugins in here, instead of separate, slower script files.

Binary file not shown.

View File

@@ -1,59 +0,0 @@
// call PROFILE.show() to show the profileViewer
var PROFILE = {
init : function(bool) {
// define what objects, constructors and functions you want to profile
// documentation here: http://developer.yahoo.com/yui/profiler/
YAHOO.tool.Profiler.registerObject("jQuery", jQuery, true);
// the following would profile all methods within constructor's prototype
// YAHOO.tool.Profiler.registerConstructor("Person");
// the following would profile the global function sayHi
// YAHOO.tool.Profiler.registerFunction("sayHi", window);
// if true is passed into init(), F9 will bring up the profiler
if (bool){
$(document).keyup(function(e){
if (e.keyCode === 120){
PROFILE.show();
$(document).unbind('keyup',arguments.callee);
}
})
}
},
//When the showProfile button is clicked, use YUI Loader to get all required
//dependencies and then show the profile:
show : function() {
var s = document.createElement('link');
s.setAttribute('rel','stylesheet');
s.setAttribute('type','text/css');
s.setAttribute('href','js/profiling/yahoo-profiling.css');
document.body.appendChild(s);
YAHOO.util.Dom.addClass(document.body, 'yui-skin-sam');
//instantiate ProfilerViewer with desired options:
var pv = new YAHOO.widget.ProfilerViewer("", {
visible: true, //expand the viewer mmediately after instantiation
showChart: true,
// base:"../../build/",
swfUrl: "js/profiling/charts.swf"
});
}
};
// check some global debug variable to see if we should be profiling..
if (true) { PROFILE.init(true) }

View File

@@ -1,7 +0,0 @@
/*
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
Code licensed under the BSD License:
http://developer.yahoo.net/yui/license.txt
version: 2.7.0
*/
.yui-skin-sam .yui-pv{background-color:#4a4a4a;font:arial;position:relative;width:99%;z-index:1000;margin-bottom:1em;overflow:hidden;}.yui-skin-sam .yui-pv .hd{background:url(http://yui.yahooapis.com/2.7.0/build/profilerviewer/assets/skins/sam/header_background.png) repeat-x;min-height:30px;overflow:hidden;zoom:1;padding:2px 0;}.yui-skin-sam .yui-pv .hd h4{padding:8px 10px;margin:0;font:bold 14px arial;color:#fff;}.yui-skin-sam .yui-pv .hd a{background:#3f6bc3;font:bold 11px arial;color:#fff;padding:4px;margin:3px 10px 0 0;border:1px solid #3f567d;cursor:pointer;display:block;float:right;}.yui-skin-sam .yui-pv .hd span{display:none;}.yui-skin-sam .yui-pv .hd span.yui-pv-busy{height:18px;width:18px;background:url(http://yui.yahooapis.com/2.7.0/build/profilerviewer/assets/skins/sam/wait.gif) no-repeat;overflow:hidden;display:block;float:right;margin:4px 10px 0 0;}.yui-skin-sam .yui-pv .hd:after,.yui-pv .bd:after,.yui-skin-sam .yui-pv-chartlegend dl:after{content:'.';visibility:hidden;clear:left;height:0;display:block;}.yui-skin-sam .yui-pv .bd{position:relative;zoom:1;overflow-x:auto;overflow-y:hidden;}.yui-skin-sam .yui-pv .yui-pv-table{padding:0 10px;margin:5px 0 10px 0;}.yui-skin-sam .yui-pv .yui-pv-table .yui-dt-bd td{color:#eeee5c;font:12px arial;}.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-odd{background:#929292;}.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-even{background:#58637a;}.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-even td.yui-dt-asc,.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-even td.yui-dt-desc{background:#384970;}.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-odd td.yui-dt-asc,.yui-skin-sam .yui-pv .yui-pv-table tr.yui-dt-odd td.yui-dt-desc{background:#6F6E6E;}.yui-skin-sam .yui-pv .yui-pv-table .yui-dt-hd th{background-image:none;background:#2E2D2D;}.yui-skin-sam .yui-pv th.yui-dt-asc .yui-dt-liner{background:transparent url(http://yui.yahooapis.com/2.7.0/build/profilerviewer/assets/skins/sam/asc.gif) no-repeat scroll right center;}.yui-skin-sam .yui-pv th.yui-dt-desc .yui-dt-liner{background:transparent url(http://yui.yahooapis.com/2.7.0/build/profilerviewer/assets/skins/sam/desc.gif) no-repeat scroll right center;}.yui-skin-sam .yui-pv .yui-pv-table .yui-dt-hd th a{color:#fff;font:bold 12px arial;}.yui-skin-sam .yui-pv .yui-pv-table .yui-dt-hd th.yui-dt-asc,.yui-skin-sam .yui-pv .yui-pv-table .yui-dt-hd th.yui-dt-desc{background:#333;}.yui-skin-sam .yui-pv-chartcontainer{padding:0 10px;}.yui-skin-sam .yui-pv-chart{height:250px;clear:right;margin:5px 0 0 0;color:#fff;}.yui-skin-sam .yui-pv-chartlegend div{float:right;margin:0 0 0 10px;_width:250px;}.yui-skin-sam .yui-pv-chartlegend dl{border:1px solid #999;padding:.2em 0 .2em .5em;zoom:1;margin:5px 0;}.yui-skin-sam .yui-pv-chartlegend dt{float:left;display:block;height:.7em;width:.7em;padding:0;}.yui-skin-sam .yui-pv-chartlegend dd{float:left;display:block;color:#fff;margin:0 1em 0 .5em;padding:0;font:11px arial;}.yui-skin-sam .yui-pv-minimized{height:35px;}.yui-skin-sam .yui-pv-minimized .bd{top:-3000px;}.yui-skin-sam .yui-pv-minimized .hd a.yui-pv-refresh{display:none;}

File diff suppressed because one or more lines are too long

View File

@@ -1,108 +0,0 @@
# Set another default user than root for security reasons
user www www;
# As a thumb rule: One per CPU. If you are serving a large amount
# of static files, which requires blocking disk reads, you may want
# to increase this from the number of cpu_cores available on your
# system.
#
# The maximum number of connections for Nginx is calculated by:
# max_clients = worker_processes * worker_connections
worker_processes 1;
# Maximum file descriptors that can be opened per process
# This should be > worker_connections
worker_rlimit_nofile 8192;
events {
# When you need > 8000 * cpu_cores connections, you start optimizing
# your OS, and this is probably the point at where you hire people
# who are smarter than you, this is *a lot* of requests.
worker_connections 8000;
# This sets up some smart queueing for accept(2)'ing requests
# Set it to "on" if you have > worker_processes
accept_mutex off;
# These settings are OS specific, by defualt Nginx uses select(2),
# however, for a large number of requests epoll(2) and kqueue(2)
# are generally faster than the default (select(2))
# use epoll; # enable for Linux 2.6+
# use kqueue; # enable for *BSD (FreeBSD, OS X, ..)
}
# Change these paths to somewhere that suits you!
error_log logs/error.log;
pid logs/nginx.pid;
http {
# Set the mime-types
include mime.types;
# And the fallback mime-type
default_type application/octet-stream;
# Format for our log files
log_format main '$remote_addr - $remote_user [$time_local] $status '
'"$request" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# Click tracking!
access_log logs/access.log main;
# ~2 seconds is often enough for HTML/CSS, but connections in
# Nginx are cheap, so generally it's safe to increase it
keepalive_timeout 5;
# You usually want to serve static files with Nginx
sendfile on;
tcp_nopush on; # off may be better for Comet/long-poll stuff
tcp_nodelay off; # on may be better for Comet/long-poll stuff
# Enable Gzip
gzip on;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_min_length 1100;
gzip_buffers 4 8k;
gzip_proxied any;
gzip_types text/html text/plain text/xml application/xml application/xml+rss text/css text/javascript application/javascript application/json;
gzip_static on;
gzip_proxied expired no-cache no-store private auth;
gzip_disable "MSIE [1-6]\.";
gzip_vary on;
server {
# listen 80 default deferred; # for Linux
# listen 80 default accept_filter=httpready; # for FreeBSD
listen 80 default;
# e.g. "localhost" to accept all connections, or "www.example.com"
# to handle the requests for "example.com" (and www.example.com)
server_name _;
# Path for static files
root /sites/example.com/public;
expires 1M;
# Static assets
location ~* ^.+\.(manifest)$ {
expires -1D;
root /sites/example.com/public;
access_log logs/static.log;
}
location ~* ^.+\.(ico|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
# Only set expires max IFF the file is a static file and exists
if (-f $request_filename) {
expires max;
root /sites/example.com/public;
access_log logs/static.log;
}
}
}
}

View File

@@ -6,9 +6,9 @@
<!-- reference your own javascript files here -->
<script src="../js/modernizr-1.5.min.js"></script>
<script src="../js/libs/modernizr-1.7.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<script src="../js/plugins.js"></script>
<script src="../js/script.js"></script>

File diff suppressed because it is too large Load Diff

View File

@@ -1,204 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- web.config contributed to html5boilerplate by Velir : velir.com -->
<configuration>
<configSections>
<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere" />
<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
<section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
</sectionGroup>
</sectionGroup>
</sectionGroup>
</configSections>
<appSettings />
<connectionStrings />
<system.web>
<!--
Set compilation debug="true" to insert debugging
symbols into the compiled page. Because this
affects performance, set this value to true only
during development.
-->
<compilation debug="false">
<assemblies>
<add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
<add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
<add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
</assemblies>
</compilation>
<authentication mode="Windows" />
<!--
The <customErrors> section enables configuration
of what to do if/when an unhandled error occurs
during the execution of a request. Specifically,
it enables developers to configure html error pages
to be displayed in place of a error stack trace.
<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
<error statusCode="403" redirect="NoAccess.htm" />
<error statusCode="404" redirect="FileNotFound.htm" />
</customErrors>
-->
<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
<error statusCode="404" redirect="404.html" />
</customErrors>
<pages>
<controls>
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</controls>
</pages>
<httpHandlers>
<remove verb="*" path="*.asmx" />
<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false" />
</httpHandlers>
<httpModules>
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</httpModules>
</system.web>
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<providerOption name="CompilerVersion" value="v3.5" />
<providerOption name="WarnAsError" value="false" />
</compiler>
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4" type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<providerOption name="CompilerVersion" value="v3.5" />
<providerOption name="OptionInfer" value="true" />
<providerOption name="WarnAsError" value="false" />
</compiler>
</compilers>
</system.codedom>
<system.webServer>
<!--
GZip static file content. Overrides the server default which only compresses static files over 2700 bytes
-->
<httpCompression directory="%SystemDrive%\websites\_compressed" minFileSizeForComp="1024">
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
<staticTypes>
<add mimeType="text/*" enabled="true" />
<add mimeType="message/*" enabled="true" />
<add mimeType="application/javascript" enabled="true" />
<add mimeType="application/json" enabled="true" />
<add mimeType="*/*" enabled="false" />
</staticTypes>
</httpCompression>
<validation validateIntegratedModeConfiguration="false" />
<modules>
<remove name="ScriptModule" />
<add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</modules>
<handlers>
<remove name="WebServiceHandlerFactory-Integrated" />
<remove name="ScriptHandlerFactory" />
<remove name="ScriptHandlerFactoryAppServices" />
<remove name="ScriptResource" />
<add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</handlers>
<urlCompression doStaticCompression="true" />
<staticContent>
<!-- Set expire headers to 30 days for static content-->
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="30.00:00:00" />
<!-- use utf-8 encoding for anything served text/plain or text/html -->
<remove fileExtension=".css" />
<mimeMap fileExtension=".css" mimeType="text/css; charset=UTF-8" />
<remove fileExtension=".js" />
<mimeMap fileExtension=".js" mimeType="text/javascript; charset=UTF-8" />
<remove fileExtension=".json" />
<mimeMap fileExtension=".json" mimeType="application/json; charset=UTF-8" />
<remove fileExtension=".rss" />
<mimeMap fileExtension=".rss" mimeType="application/rss+xml; charset=UTF-8" />
<remove fileExtension=".html" />
<mimeMap fileExtension=".html" mimeType="text/html; charset=UTF-8" />
<remove fileExtension=".xml" />
<mimeMap fileExtension=".xml" mimeType="application/xml; charset=UTF-8" />
<!-- HTML5 Video mime types-->
<mimeMap fileExtension=".mp4" mimeType="video/mp4" />
<mimeMap fileExtension=".m4v" mimeType="video/m4v" />
<mimeMap fileExtension=".ogg" mimeType="video/ogg" />
<mimeMap fileExtension=".ogv" mimeType="video/ogg" />
<mimeMap fileExtension=".webm" mimeType="video/webm" />
<!-- Proper svg serving. Required for svg webfonts on iPad -->
<mimeMap fileExtension=".svg" mimeType="images/svg+xml" />
<mimeMap fileExtension=".svgz" mimeType="images/svg+xml" />
<!-- HTML4 Web font mime types -->
<!-- Remove default IIS mime type for .eot which is application/octet-stream -->
<remove fileExtension=".eot" />
<mimeMap fileExtension=".eot" mimeType="application/vnd.ms-fontobject" />
<mimeMap fileExtension=".otf" mimeType="font/otf" />
<mimeMap fileExtension=".woff" mimeType="font/x-woff" />
</staticContent>
<httpProtocol>
<customHeaders>
<!--
http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/
Uncomment to serve cross-domain ajax requests
<add name="Access-Control-Allow-Origin" value="*" />
-->
<!--
Force the latest IE version, in various cases when it may fall back to IE7 mode
github.com/rails/rails/commit/123eb25#commitcomment-118920
Use ChromeFrame if it's installed for a better experience for the poor IE folk
-->
<add name="X-UA-Compatible" value="IE=Edge,chrome=1" />
<!--
Allow cookies to be set from iframes (for IE only)
If needed, uncomment and specify a path or regex in the Location directive
<add name="P3P" value="policyref=&quot;/w3c/p3p.xml&quot;, CP=&quot;IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT&quot;" />
-->
</customHeaders>
</httpProtocol>
<!--
Remove the WWW from the URL.
Requires IIS Rewrite module http://learn.iis.net/page.aspx/460/using-the-url-rewrite-module/
Configuration lifted from http://nayyeri.net/remove-www-prefix-from-urls-with-url-rewrite-module-for-iis-7-0
<rewrite>
<rules>
<rule name="Remove WWW" stopProcessing="true">
<match url="^(.*)$" />
<conditions>
<add input="{HTTP_HOST}" pattern="^(www\.)(.*)$" />
</conditions>
<action type="Redirect" url="http://nayyeri.net{PATH_INFO}" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
-->
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>