[
  {
    "path": ".gitattributes",
    "content": "* text=auto"
  },
  {
    "path": ".gitignore",
    "content": "# Numerous always-ignore extensions\n*.diff\n*.err\n*.orig\n*.log\n*.rej\n*.swo\n*.swp\n*.vi\n*~\n*.sass-cache\n\n# OS or Editor folders\n.DS_Store\nThumbs.db\n.cache\n.project\n.settings\n.tmproj\n*.esproj\nnbproject\n*.sublime-project\n*.sublime-workspace\n\n# Dreamweaver added files\n_notes\ndwsync.xml\n\n# Komodo\n*.komodoproject\n.komodotools\n\n# Folders to ignore\n.hg\n.svn\n.CVS\nintermediate\npublish\n.idea\n\n# build script local files\nbuild/buildinfo.properties\nbuild/config/buildinfo.properties\n"
  },
  {
    "path": ".htaccess",
    "content": "\n# dear h5bp htaccess file,\n#   i love you.\n\n\n\n# ----------------------------------------------------------------------\n# Better website experience for IE users\n# ----------------------------------------------------------------------\n\n# Force the latest IE version, in various cases when it may fall back to IE7 mode\n#  github.com/rails/rails/commit/123eb25#commitcomment-118920\n# Use ChromeFrame if it's installed for a better experience for the poor IE folk\n\n<IfModule mod_headers.c>\n  Header set X-UA-Compatible \"IE=Edge,chrome=1\"\n  # mod_headers can't match by content-type, but we don't want to send this header on *everything*...\n  <FilesMatch \"\\.(js|css|gif|png|jpe?g|pdf|xml|oga|ogg|m4a|ogv|mp4|m4v|webm|svg|svgz|eot|ttf|otf|woff|ico|webp|appcache|manifest|htc|crx|oex|xpi|safariextz|vcf)$\" >\n    Header unset X-UA-Compatible\n  </FilesMatch>\n</IfModule>\n\n\n# ----------------------------------------------------------------------\n# Cross-domain AJAX requests\n# ----------------------------------------------------------------------\n\n# Serve cross-domain Ajax requests, disabled by default.\n# enable-cors.org\n# code.google.com/p/html5security/wiki/CrossOriginRequestSecurity\n\n#  <IfModule mod_headers.c>\n#    Header set Access-Control-Allow-Origin \"*\"\n#  </IfModule>\n\n\n# ----------------------------------------------------------------------\n# CORS-enabled images (@crossorigin)\n# ----------------------------------------------------------------------\n\n# Send CORS headers if browsers request them; enabled by default for images.\n# developer.mozilla.org/en/CORS_Enabled_Image\n# blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html\n# hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/\n# wiki.mozilla.org/Security/Reviews/crossoriginAttribute\n\n<IfModule mod_setenvif.c>\n  <IfModule mod_headers.c>\n    # mod_headers, y u no match by Content-Type?!\n    <FilesMatch \"\\.(gif|png|jpe?g|svg|svgz|ico|webp)$\">\n      SetEnvIf Origin \":\" IS_CORS\n      Header set Access-Control-Allow-Origin \"*\" env=IS_CORS\n    </FilesMatch>\n  </IfModule>\n</IfModule>\n\n\n# ----------------------------------------------------------------------\n# Webfont access\n# ----------------------------------------------------------------------\n\n# Allow access from all domains for webfonts.\n# Alternatively you could only whitelist your\n# subdomains like \"subdomain.example.com\".\n\n<IfModule mod_headers.c>\n  <FilesMatch \"\\.(ttf|ttc|otf|eot|woff|font.css)$\">\n    Header set Access-Control-Allow-Origin \"*\"\n  </FilesMatch>\n</IfModule>\n\n\n\n# ----------------------------------------------------------------------\n# Proper MIME type for all files\n# ----------------------------------------------------------------------\n\n\n# JavaScript\n#   Normalize to standard type (it's sniffed in IE anyways)\n#   tools.ietf.org/html/rfc4329#section-7.2\nAddType application/javascript         js\n\n# Audio\nAddType audio/ogg                      oga ogg\nAddType audio/mp4                      m4a\n\n# Video\nAddType video/ogg                      ogv\nAddType video/mp4                      mp4 m4v\nAddType video/webm                     webm\n\n# SVG\n#   Required for svg webfonts on iPad\n#   twitter.com/FontSquirrel/status/14855840545\nAddType     image/svg+xml              svg svgz\nAddEncoding gzip                       svgz\n\n# Webfonts\nAddType application/vnd.ms-fontobject  eot\nAddType application/x-font-ttf         ttf ttc\nAddType font/opentype                  otf\nAddType application/x-font-woff        woff\n\n# Assorted types\nAddType image/x-icon                        ico\nAddType image/webp                          webp\nAddType text/cache-manifest                 appcache manifest\nAddType text/x-component                    htc\nAddType application/x-chrome-extension      crx\nAddType application/x-opera-extension       oex\nAddType application/x-xpinstall             xpi\nAddType application/octet-stream            safariextz\nAddType application/x-web-app-manifest+json webapp\nAddType text/x-vcard                        vcf\n\n\n\n# ----------------------------------------------------------------------\n# Allow concatenation from within specific js and css files\n# ----------------------------------------------------------------------\n\n# e.g. Inside of script.combined.js you could have\n#   <!--#include file=\"libs/jquery-1.5.0.min.js\" -->\n#   <!--#include file=\"plugins/jquery.idletimer.js\" -->\n# and they would be included into this single file.\n\n# This is not in use in the boilerplate as it stands. You may\n# choose to name your files in this way for this advantage or\n# concatenate and minify them manually.\n# Disabled by default.\n\n#<FilesMatch \"\\.combined\\.js$\">\n#  Options +Includes\n#  AddOutputFilterByType INCLUDES application/javascript application/json\n#  SetOutputFilter INCLUDES\n#</FilesMatch>\n#<FilesMatch \"\\.combined\\.css$\">\n#  Options +Includes\n#  AddOutputFilterByType INCLUDES text/css\n#  SetOutputFilter INCLUDES\n#</FilesMatch>\n\n\n# ----------------------------------------------------------------------\n# Gzip compression\n# ----------------------------------------------------------------------\n\n<IfModule mod_deflate.c>\n\n  # Force deflate for mangled headers developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping/\n  <IfModule mod_setenvif.c>\n    <IfModule mod_headers.c>\n      SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\\s*,?\\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding\n      RequestHeader append Accept-Encoding \"gzip,deflate\" env=HAVE_Accept-Encoding\n    </IfModule>\n  </IfModule>\n\n  # HTML, TXT, CSS, JavaScript, JSON, XML, HTC:\n  <IfModule filter_module>\n    FilterDeclare   COMPRESS\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/html\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/css\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/plain\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/xml\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $text/x-component\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/javascript\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/json\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/xml\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/xhtml+xml\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/rss+xml\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/atom+xml\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/vnd.ms-fontobject\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $image/svg+xml\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $image/x-icon\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $application/x-font-ttf\n    FilterProvider  COMPRESS  DEFLATE resp=Content-Type $font/opentype\n    FilterChain     COMPRESS\n    FilterProtocol  COMPRESS  DEFLATE change=yes;byteranges=no\n  </IfModule>\n\n  <IfModule !mod_filter.c>\n    # Legacy versions of Apache\n    AddOutputFilterByType DEFLATE text/html text/plain text/css application/json\n    AddOutputFilterByType DEFLATE application/javascript\n    AddOutputFilterByType DEFLATE text/xml application/xml text/x-component\n    AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml\n    AddOutputFilterByType DEFLATE image/x-icon image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype\n  </IfModule>\n\n</IfModule>\n\n\n# ----------------------------------------------------------------------\n# Expires headers (for better cache control)\n# ----------------------------------------------------------------------\n\n# These are pretty far-future expires headers.\n# They assume you control versioning with cachebusting query params like\n#   <script src=\"application.js?20100608\">\n# Additionally, consider that outdated proxies may miscache\n#   www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/\n\n# If you don't use filenames to version, lower the CSS  and JS to something like\n#   \"access plus 1 week\" or so.\n\n<IfModule mod_expires.c>\n  ExpiresActive on\n\n# Perhaps better to whitelist expires rules? Perhaps.\n  ExpiresDefault                          \"access plus 1 month\"\n\n# cache.appcache needs re-requests in FF 3.6 (thanks Remy ~Introducing HTML5)\n  ExpiresByType text/cache-manifest       \"access plus 0 seconds\"\n\n# Your document html\n  ExpiresByType text/html                 \"access plus 0 seconds\"\n\n# Data\n  ExpiresByType text/xml                  \"access plus 0 seconds\"\n  ExpiresByType application/xml           \"access plus 0 seconds\"\n  ExpiresByType application/json          \"access plus 0 seconds\"\n\n# Feed\n  ExpiresByType application/rss+xml       \"access plus 1 hour\"\n  ExpiresByType application/atom+xml      \"access plus 1 hour\"\n\n# Favicon (cannot be renamed)\n  ExpiresByType image/x-icon              \"access plus 1 week\"\n\n# Media: images, video, audio\n  ExpiresByType image/gif                 \"access plus 1 month\"\n  ExpiresByType image/png                 \"access plus 1 month\"\n  ExpiresByType image/jpg                 \"access plus 1 month\"\n  ExpiresByType image/jpeg                \"access plus 1 month\"\n  ExpiresByType video/ogg                 \"access plus 1 month\"\n  ExpiresByType audio/ogg                 \"access plus 1 month\"\n  ExpiresByType video/mp4                 \"access plus 1 month\"\n  ExpiresByType video/webm                \"access plus 1 month\"\n\n# HTC files  (css3pie)\n  ExpiresByType text/x-component          \"access plus 1 month\"\n\n# Webfonts\n  ExpiresByType application/x-font-ttf    \"access plus 1 month\"\n  ExpiresByType font/opentype             \"access plus 1 month\"\n  ExpiresByType application/x-font-woff   \"access plus 1 month\"\n  ExpiresByType image/svg+xml             \"access plus 1 month\"\n  ExpiresByType application/vnd.ms-fontobject \"access plus 1 month\"\n\n# CSS and JavaScript\n  ExpiresByType text/css                  \"access plus 1 year\"\n  ExpiresByType application/javascript    \"access plus 1 year\"\n\n  <IfModule mod_headers.c>\n    Header append Cache-Control \"public\"\n  </IfModule>\n\n</IfModule>\n\n\n\n# ----------------------------------------------------------------------\n# ETag removal\n# ----------------------------------------------------------------------\n\n# FileETag None is not enough for every server.\n<IfModule mod_headers.c>\n  Header unset ETag\n</IfModule>\n\n# Since we're sending far-future expires, we don't need ETags for\n# static content.\n#   developer.yahoo.com/performance/rules.html#etags\nFileETag None\n\n\n\n# ----------------------------------------------------------------------\n# Stop screen flicker in IE on CSS rollovers\n# ----------------------------------------------------------------------\n\n# The following directives stop screen flicker in IE on CSS rollovers - in\n# combination with the \"ExpiresByType\" rules for images (see above). If\n# needed, un-comment the following rules.\n\n# BrowserMatch \"MSIE\" brokenvary=1\n# BrowserMatch \"Mozilla/4.[0-9]{2}\" brokenvary=1\n# BrowserMatch \"Opera\" !brokenvary\n# SetEnvIf brokenvary 1 force-no-vary\n\n\n\n# ----------------------------------------------------------------------\n# Cookie setting from iframes\n# ----------------------------------------------------------------------\n\n# Allow cookies to be set from iframes (for IE only)\n# If needed, uncomment and specify a path or regex in the Location directive\n\n# <IfModule mod_headers.c>\n#   <Location />\n#     Header set P3P \"policyref=\\\"/w3c/p3p.xml\\\", CP=\\\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\\\"\"\n#   </Location>\n# </IfModule>\n\n\n\n# ----------------------------------------------------------------------\n# Start rewrite engine\n# ----------------------------------------------------------------------\n\n# Turning on the rewrite engine is necessary for the following rules and features.\n# FollowSymLinks must be enabled for this to work.\n\n<IfModule mod_rewrite.c>\n  Options +FollowSymlinks\n  RewriteEngine On\n</IfModule>\n\n\n\n# ----------------------------------------------------------------------\n# Suppress or force the \"www.\" at the beginning of URLs\n# ----------------------------------------------------------------------\n\n# The same content should never be available under two different URLs - especially not with and\n# without \"www.\" at the beginning, since this can cause SEO problems (duplicate content).\n# That's why you should choose one of the alternatives and redirect the other one.\n\n# By default option 1 (no \"www.\") is activated. Remember: Shorter URLs are sexier.\n# no-www.org/faq.php?q=class_b\n\n# If you rather want to use option 2, just comment out all option 1 lines\n# and uncomment option 2.\n# IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME!\n\n# ----------------------------------------------------------------------\n\n# Option 1:\n# Rewrite \"www.example.com -> example.com\"\n\n<IfModule mod_rewrite.c>\n  RewriteCond %{HTTPS} !=on\n  RewriteCond %{HTTP_HOST} ^www\\.(.+)$ [NC]\n  RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]\n</IfModule>\n\n# ----------------------------------------------------------------------\n\n# Option 2:\n# To rewrite \"example.com -> www.example.com\" uncomment the following lines.\n# Be aware that the following rule might not be a good idea if you\n# use \"real\" subdomains for certain parts of your website.\n\n# <IfModule mod_rewrite.c>\n#   RewriteCond %{HTTPS} !=on\n#   RewriteCond %{HTTP_HOST} !^www\\..+$ [NC]\n#   RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]\n# </IfModule>\n\n\n\n# ----------------------------------------------------------------------\n# Built-in filename-based cache busting\n# ----------------------------------------------------------------------\n\n# If you're not using the build script to manage your filename version revving,\n# you might want to consider enabling this, which will route requests for\n# /css/style.20110203.css to /css/style.css\n\n# To understand why this is important and a better idea than all.css?v1231,\n# read: github.com/h5bp/html5-boilerplate/wiki/Version-Control-with-Cachebusting\n\n# Uncomment to enable.\n# <IfModule mod_rewrite.c>\n#   RewriteCond %{REQUEST_FILENAME} !-f\n#   RewriteCond %{REQUEST_FILENAME} !-d\n#   RewriteRule ^(.+)\\.(\\d+)\\.(js|css|png|jpg|gif)$ $1.$3 [L]\n# </IfModule>\n\n\n\n# ----------------------------------------------------------------------\n# Prevent SSL cert warnings\n# ----------------------------------------------------------------------\n\n# Rewrite secure requests properly to prevent SSL cert warnings, e.g. prevent\n# https://www.example.com when your cert only allows https://secure.example.com\n# Uncomment the following lines to use this feature.\n\n# <IfModule mod_rewrite.c>\n#   RewriteCond %{SERVER_PORT} !^443\n#   RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L]\n# </IfModule>\n\n\n\n# ----------------------------------------------------------------------\n# Prevent 404 errors for non-existing redirected folders\n# ----------------------------------------------------------------------\n\n# without -MultiViews, Apache will give a 404 for a rewrite if a folder of the same name does not exist\n#   e.g. /blog/hello : webmasterworld.com/apache/3808792.htm\n\nOptions -MultiViews\n\n\n\n# ----------------------------------------------------------------------\n# Custom 404 page\n# ----------------------------------------------------------------------\n\n# You can add custom pages to handle 500 or 403 pretty easily, if you like.\nErrorDocument 404 /404.html\n\n\n\n# ----------------------------------------------------------------------\n# UTF-8 encoding\n# ----------------------------------------------------------------------\n\n# Use UTF-8 encoding for anything served text/plain or text/html\nAddDefaultCharset utf-8\n\n# Force UTF-8 for a number of file formats\nAddCharset utf-8 .css .js .xml .json .rss .atom\n\n\n\n# ----------------------------------------------------------------------\n# A little more security\n# ----------------------------------------------------------------------\n\n\n# Do we want to advertise the exact version number of Apache we're running?\n# Probably not.\n## This can only be enabled if used in httpd.conf - It will not work in .htaccess\n# ServerTokens Prod\n\n\n# \"-Indexes\" will have Apache block users from browsing folders without a default document\n# Usually you should leave this activated, because you shouldn't allow everybody to surf through\n# every folder on your server (which includes rather private places like CMS system folders).\n<IfModule mod_autoindex.c>\n  Options -Indexes\n</IfModule>\n\n\n# Block access to \"hidden\" directories whose names begin with a period. This\n# includes directories used by version control systems such as Subversion or Git.\n<IfModule mod_rewrite.c>\n  RewriteRule \"(^|/)\\.\" - [F]\n</IfModule>\n\n\n# Block access to backup and source files\n# This files may be left by some text/html editors and\n# pose a great security danger, when someone can access them\n<FilesMatch \"\\.(bak|config|sql|fla|psd|ini|log|sh|inc|~|swp)$\">\n  Order allow,deny\n  Deny from all\n  Satisfy All\n</FilesMatch>\n\n\n# If your server is not already configured as such, the following directive\n# should be uncommented in order to set PHP's register_globals option to OFF.\n# This closes a major security hole that is abused by most XSS (cross-site\n# scripting) attacks. For more information: http://php.net/register_globals\n#\n# IF REGISTER_GLOBALS DIRECTIVE CAUSES 500 INTERNAL SERVER ERRORS :\n#\n# Your server does not allow PHP directives to be set via .htaccess. In that\n# case you must make this change in your php.ini file instead. If you are\n# using a commercial web host, contact the administrators for assistance in\n# doing this. Not all servers allow local php.ini files, and they should\n# include all PHP configurations (not just this one), or you will effectively\n# reset everything to PHP defaults. Consult www.php.net for more detailed\n# information about setting PHP directives.\n\n# php_flag register_globals Off\n\n# Rename session cookie to something else, than PHPSESSID\n# php_value session.name sid\n\n# Do not show you are using PHP\n# Note: Move this line to php.ini since it won't work in .htaccess\n# php_flag expose_php Off\n\n# Level of log detail - log all errors\n# php_value error_reporting -1\n\n# Write errors to log file\n# php_flag log_errors On\n\n# Do not display errors in browser (production - Off, development - On)\n# php_flag display_errors Off\n\n# Do not display startup errors (production - Off, development - On)\n# php_flag display_startup_errors Off\n\n# Format errors in plain text\n# Note: Leave this setting 'On' for xdebug's var_dump() output\n# php_flag html_errors Off\n\n# Show multiple occurrence of error\n# php_flag ignore_repeated_errors Off\n\n# Show same errors from different sources\n# php_flag ignore_repeated_source Off\n\n# Size limit for error messages\n# php_value log_errors_max_len 1024\n\n# Don't precede error with string (doesn't accept empty string, use whitespace if you need)\n# php_value error_prepend_string \" \"\n\n# Don't prepend to error (doesn't accept empty string, use whitespace if you need)\n# php_value error_append_string \" \"\n\n# Increase cookie security\n<IfModule php5_module>\n  php_value session.cookie_httponly true\n</IfModule>\n"
  },
  {
    "path": "404.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <title>Page Not Found</title>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <style>\n\n        * {\n            line-height: 1.2;\n            margin: 0;\n        }\n\n        html {\n            color: #888;\n            display: table;\n            font-family: sans-serif;\n            height: 100%;\n            text-align: center;\n            width: 100%;\n        }\n\n        body {\n            display: table-cell;\n            vertical-align: middle;\n            margin: 2em auto;\n        }\n\n        h1 {\n            color: #555;\n            font-size: 2em;\n            font-weight: 400;\n        }\n\n        p {\n            margin: 0 auto;\n            width: 280px;\n        }\n\n        @media only screen and (max-width: 280px) {\n\n            body, p {\n                width: 95%;\n            }\n\n            h1 {\n                font-size: 1.5em;\n                margin: 0 0 0.3em;\n            }\n\n        }\n\n    </style>\n</head>\n<body>\n    <h1>Page Not Found</h1>\n    <p>Sorry, but the page you were trying to view does not exist.</p>\n</body>\n</html>\n<!-- IE needs 512+ bytes: http://blogs.msdn.com/b/ieinternals/archive/2010/08/19/http-error-pages-in-internet-explorer.aspx -->\n"
  },
  {
    "path": "README.md",
    "content": "\nThis site is mostly kaput. It hasn't been touched in a while. \n\n------------------------------------------------\n\n\n# movethewebforward.org\n\nYou ♡ Web Standards. You maybe even feel compelled to “give back” to the community. Curious about where to start? We’re here to help.\n\n## Contributing\n\nDo you have some ideas for ways that all developers—from the seasoned professionals to those donning their first blue beanie—can get involved, learn more, and help move web standards forward? [Chime in here](https://etherpad.mozilla.org/igotmybeanie) or look at the github issues!. We'll be adding new ideas, resources and tasks regularly so feel free to check back often.\n\n## IRC channel\n\nWe're in #movethewebforward on freenode IRC. For those without an IRC client see <http://webchat.freenode.net/?channels=movethewebforward>\n\n## Staging server\n\nView the current site at <http://h5bp.github.com/movethewebforward/>\n\n## Dev Notes\n\nAdd `?mobile` to the end of `index.html` to see assets as they will appear on mobile devices (determined by screen size, really), and “?basic” to see assets as they will appear in browsers that don’t support media queries. I haven’t done much in the way of styling either way. There’s quite a bit of behind-the-scenes logic goin’ on that we most definitely will not need for a one-pager, so a lot of that will be removed very soon.\n"
  },
  {
    "path": "ar/ar.css",
    "content": "body {\n        text-align: right;\n        direction: rtl;\n}\n.hed-lead {\n    background: url(rtl-webasaurs.gif) center 0 no-repeat;\n}\n.hed {\n        float: right;\n}\n/* inverse the direction of some block */\n.inverse_dir{\n        direction:ltr;\n}\n.inverse_align{\n        text-align:left;\n}\n.task li:before,\n.resources > li:before {\n    float: right;\n    padding: .1em 0 0 .6em;\n}\nnav li {\n        padding: 0 10px 0 0;\n        width: 285px;\n}\nnav a:hover, nav a:focus, nav a.active {\n        outline:none;\n}\n  .col-a {\n                float: right;\n        }\n  .col-b {\n                float: left;\n        }\n\n@media screen and (min-width: 800px) {\n        .col-split p {\n                padding: 0 2px 1em 0;\n        }\n}\n"
  },
  {
    "path": "ar/index.html",
    "content": "<!DOCTYPE html public \"i ♥ the web\">\n<!--[if lt IE 9]>      <html class=\"no-js oldie no-fontface\" lang=\"ar\" dir=\"rtl\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html class=\"no-js no-fontface\" lang=\"ar\" dir=\"rtl\">   <!--<![endif]-->\n<head>\n    <meta charset=\"utf-8\">\n    <title>إدفع الويب إلى الأمام | دليلك للمشاركة فى معايير المتصفحات وتطوير الويب.</title>\n    <meta name=\"description\" content=\"What you can do as a front-end developer\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, minimum-scale=1\">\n\n    <!-- For iPhone 4 with high-resolution Retina display: -->\n    <link rel=\"apple-touch-icon-precomposed\" sizes=\"114x114\" href=\"apple-touch-icon-114x114-precomposed.png\">\n    <!-- For first-generation iPad: -->\n    <link rel=\"apple-touch-icon-precomposed\" sizes=\"72x72\" href=\"apple-touch-icon-72x72-precomposed.png\">\n    <!-- For non-Retina iPhone, iPod Touch, and Android 2.1+ devices: -->\n    <link rel=\"apple-touch-icon-precomposed\" href=\"apple-touch-icon-precomposed.png\">\n\n    <link rel=\"stylesheet\" href=\"/css/style.css\">\n        <link rel=\"stylesheet\" href=\"ar.css\">\n\n    <!-- Should be combined: -->\n    <script src=\"/js/libs/modernizr.min.js\"></script>\n    <script src=\"/js/controller.js\"></script>\n</head>\n\n<body>\n  <b class=\"gimmick\"><i></i><i></i><i></i></b>\n    <header class=\"col-ab\">\n        <div class=\"lead\">\n            <h1 class=\"hed-lead\">إدفع الويب إلى الأمام<span></span></h1>\n            <h2 class=\"subhed-lead\">يمكنك أن تجعل الويب رائع كما تحب أن يكون</h2>\n            <p class=\"subhed\">تحب <a href=\"http://bit.ly/xuni7z\">معايير الويب</a> &ndash;&nbsp;وتريد أن تشارك فى مجتمع الويب. وتريد أن تعرف من أين تبدأ؟ <b>نحن هنا لمساعدتك</b></p>\n        </div>\n        <div class=\"col-split\">\n            <p>سواء كنت مطور مواقع موهوب تبنى مواقع منذ بداية ظهور الويب, أو أنك هاوى تستمتع بتطوير بعض المواقع, فإنك تستجد هنا طرق تمكنك من المشاركة فى مجتمع الويب. فى الأسفل, وضعنا طرق كثيرة تمكنك من المشاركة.  </p>\n            <p>هدفنا أن نجعل من السهل لأى شخص أن يبدأ فى المشاركة فى مجتمع الويب, إما بالمعرفة أكثر حول طريقة عمل الويب, أو أن يتعلم من الأخرين أو يعلمهم. الويب تطور بفضل أشخاصاً مثلك, ونحن نريد أن نجعل من السهل لك أيضا أن تشارك.</p>\n        </div>\n    </header>\n\n    <div id=\"nav_container\">\n      <nav id=\"toc\">\n        <ul>\n          <li><a href=#levelup>إرتقي بمستواك</a></li>\n          <li><a href=#digdeep>تعمق أكثر</a></li>\n          <li><a href=#virtuoso>مبدع</a></li>\n        </ul>\n      </nav>\n    </div>\n\n    <article class=\"section\">\n        <div class=\"standout\" id=levelup>\n            <h1 class=\"hed\">إرتقي بمستواك</h1>\n            <h2 class=\"subhed\">عندما تعمل شئ تكون جيداً فيه. إذاً تعال نغوص فى مجتمع الويب</h2>\n        </div>\n\n\n        <section id=\"learn\" class=\"col-ab\">\n            <div class=\"col-a\">\n              <h1 class=\"hed\">تعلّم</h1>\n              <p>أحد الأشياء الرائعة عن الويب هي انه  يتغير بإستمرار. ولربما كان هذا التغيير شاسع ومن الصعب إدراكه, فنحن هنا لنساعدك على اللحاق بهذه التغيرات وعلى فهمها  - هنا ستجد مصادر كثيرة تساعدك على معرفة كيف تعمل برامج تصفح الأنترنت, وتساعدك على أن تكون على علم دائم بالتطورات والتغيرات التى تحدث فى هذة المتصفحات.</p>\n\n              <h2 id=\"how_do_i_keep_up_with_what8217s_landing_in_browsers\" class=\"subhed\">كيف أكون على علم دائم بالجديد فى هذة المتصفحات؟</h2>\n              <ul>\n                <li><a href=\"http://updates.html5rocks.com/2011/10/Keeping-up-with-HTML5-and-browser-support\">Keeping up with HTML5 and browser support</a><span> - قائمة بمواقع ومصادر ترصد كل تغيير يحدث</span></li>\n                <li><a href=\"http://peter.sh/\">Peter Beverloo&#8217;s Blog</a><span> - تحديثات أسبوعية بكل جديد فى &nbsp; WebKit و Chrome</span></li>\n                <li><a href=\"http://blog.whatwg.org/\">The WHATWG Blog</a><span> - تلخيصات أسبوعية بكل مستجدات معايير الويب</span></li>\n                <li><a href=\"http://www.w3.org/QA/archive/open_web/\">W3C&#8217;s open web</a><span> - تحديثات أسبوعية بكل جديد فى  &nbsp; the Open Web Platform</span></li>\n                <li><a href=\"http://my.opera.com/ODIN/blog/\">Opera Developer News</a><span> - رصد تطورات  &nbsp; Opera's web platform</span>\n                <li><a href=\"http://updates.html5rocks.com\">HTML5 Rocks updates</a><span> - الأخبار الهامة والعاجلة عن HTML5 و Chrome</span>\n                <li><a href=\"http://hacks.mozilla.org/\">Mozilla Hacks</a><span> - تقدم تطبيقات رائعة ونظرة على إمكانيات ال HTML5</span>\n                <li><a href=\"http://blogs.msdn.com/b/ie/\">IE Blog</a><span> - تحديثات المتصفح IE</span>\n              </ul>\n\n                                <div class=\"inverse_dir\">\n              <h3 id=\"follow_them_on_twitter\" class=\"subhed\">تابعهم على تويتر</h3>\n                <p>\n                  من الجيد متابعة الحسابات الأتية </br>\n                                  (Opera developer relations) <a href=\"http://twitter.com/oDevRel\">@oDevRel</a>  </br>\n                                  (Chrome developer relations) <a href=\"http://twitter.com/ChromiumDev\">@ChromiumDev</a> </br>\n                                  (Mozilla's web developer outpost) <a href=\"http://twitter.com/mozhacks\">@mozhacks</a> </br>\n                                  (Internet Explorer Team) <a href=\"http://twitter.com/ie\">@IE</a>\n                </p>\n                                </div>\n              <h2 id=\"how_do_i_understand_how_browsers_work\" class=\"subhed\">كيف أعرف طريقة عمل المتصفح؟</h2>\n\n              <ul>\n                <li><a href=\"http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/\">How Browsers Work: Behind the Scenes of Modern Web Browsers</a> - مقال فى العمق عن كيفية عمل المتصفحات</li>\n                <li><a href=\"http://ontwik.com/javascript/txjs-2011-a9-alex-russell-life-of-a-button-element/?utm_source=feedburner&utm_medium=twitter&utm_campaign=Feed%3A+Ontwik+%28Ontwik%29\">Life of a &lt;button> element -by Alex Russell</a> - فيديو رائع عن كيف تتعامل المتصفحات الحديثة مع ال CSS, وماذا يحدث خلف الستار لتطبيق ال  CSS</li>\n              </ul>\n\n              <h2 id=\"other_learning_resources\" class=\"subhed\">مصادر تعليمية أخرى</h2>\n\n              <ul>\n                <li><a href=\"http://css-tricks.com\">CSS-tricks</a><span> -  مدونة تقدم لمصممين المواقع مقالات رائعة ودروس ومواد للتحميل</span></li>\n                <li><a href=\"http://html5doctor.com\">HTML5doctor</a><span> - مصدر رائع لمن يريد تعلم ال HTML5, وطريقة عملها, وطريقة تطبيقها اليوم.</span></li>\n                <li><a href=\"http://diveintohtml5.info/\">Dive into HTML5</a><span> - تقدم نظرة عميقة على بعض إمكانيات ال HTML5</span></li>\n                <li><a href=\"http://addyosmani.com/blog/\">Addy Osmani&#8217;s blog</a><span> - عدد هائل من المقلات للذين يريدون تعلم jQuery, JavaScript, HTML5, CSS3.</span></li>\n                <li><a href=\"http://paulirish.com\">Paul Irish&#8217;s blog</a><span> - مدونة مهمة تساعدك على تطوير مواقع رائعة – وتأتيك بكل جديد عن تقنيات تطوير المواقع. </span></li>\n                <li><a href=\"http://dev.opera.com\">Dev.Opera</a><span> - مقالات تعليم إمكانيات ال HTML5</span></li>\n                <li><a href=\"http://paulirish.com/2011/web-browser-frontend-and-standards-feeds-to-follow/\">مصادر مهمة متنوعة عن متصفحات الويب ومعايير الويب</a> </li>\n                <li><a href=\"http://yuilibrary.com/theater/\">YUI Theater</a><span> - فيديوهات عن تقنيات الويب ألقيت فى شركة ياهو على مدار السنين</span></li>\n                <li><a href=\"http://www.adobe.com/devnet/html5.html\">Adobe Developer Connection</a><span> - مقالات وفيديوهات لتعلم HTML5 و CSS3 و mobile development.</span></li>\n              </ul>\n\n              <h2 id=\"reference_docs_wikis\" class=\"subhed\">مراجع وموسوعات</h2>\n\n              <ul>\n                <li><a href=\"https://developer.mozilla.org/en-US/\">Mozilla&#8217;s MDN )Mozilla Developer Network)</a> - مستندات و مراجع  رائعة ولا غنى عنها عن HTML, CSS, JavaScript, DOM, وأشياء أخرى. وهو أيضا مكان جيد للمشاركة - و يمكنك معرفة  <a href=\"https://developer.mozilla.org/Project:en/How_to_Help\">كيف تساهم</a> وتعلم <a href=\"https://developer.mozilla.org/Project:en/Getting_started\">كيف تبدأ</a>.</li>\n                <li><a href=\"https://developer.mozilla.org/Writing_Forward_Compatible_Websites\">Forward-compatible websites</a> - قائمة بأفضل الممارسات فى تطوير المواقع والتى ستعمل دائما حتى مع تغييرات متصفحات الويب.</li>\n                <li><a href=\"http://html5please.com/\">HTML5 Please - Use new and shiny responsibly</a> - موسوعة لتقنيات ال HTML5 , ويمكنك البحث عن تقنية معينة ومعرفة هل تستخدمها ام لا ومتى تستخدمها.</li>\n              </ul>\n          </div>\n          <div class=\"col-b\">\n            <section class=\"getinvolved\">\n              <h2 class=\"subhed\">إكتساب الخبرة؟</h2>\n              <div class=\"task\" data-hashtag=\"#learn\">\n                  <p>كل ما فى الأمر هو قراءة بعض المقالات والتغريدات لتكتسب الخبرة, ثق بنا حيثما بدأت ستجد أن الأمر يصبح أسهل.</p>\n                  <a href=\"#\" class=\"pledge\">نعم, أريد البدء</a>\n                  <div class=\"pledges\"><p>هؤلاء بعض من قرروا البدء أيضا:</p></div>\n              </div>\n            </section>\n          </div>\n          </section>\n\n        <section id=\"meetups\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">قابل مطورون أخرون</h1>\n            <p>حضور المقابلات والمؤتمرات المحلية فرصة جيدة لمقابلة المطوريين الأخرين ولمشاركة الأفكار والخبرات معهم,\n                        مواقع مثل\n                        <a href=\"http://wusu.me/\">WhatIsUpStartups</a>\n                        ستساعدك فى معرفة الأحداث والمؤتمرات القريبة منك.</p>\n          </div>\n        </section>\n        <section id=\"askhelp\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">أطلب المساعدة</h1>\n            <h2 id=\"answer_questions_and_participate_in_conversations_on_irc\" class=\"subhed\">إسأل وجاوب على الأسئلة وشارك فى المحادثات على ال\n                        <a href=\"http://bit.ly/zsq18Z\">IRC</a></h2>\n            <p><a href=\"http://richard.esplins.org/siwi/2011/07/08/getting-started-freenode-irc/\">كيف تبدأ مع ال irc و موقع freenode</a></p>\n            <ul>\n              <li><b>قنوات او غرف IRC هامة على موقع <a href=\"http://webchat.freenode.net\">irc.freenode.net</a>:</b> </br>\n                          <p class=\"inverse_dir\">#html5 / #css / #javascript / #whatwg / #jquery / #yui / #dojo / #web/ #bbg </p></li>\n               <li id=\"mozilla_irc\">وقناة  js#  على  <a href=\"http://irc.mozilla.org\">irc.mozilla.org</a></li>\n            </ul>\n\n            <h2 id=\"how_to_ask_for_help\" class=\"subhed\">كيف تطلب المساعدة</h2>\n            <ol class=\"tasks\">\n              <li>من الأفضل , بل يجب أن <a href=\"https://css-tricks.com/seriously-just-make-a-jsfiddle/\">تقوم بعمل jsfiddle </a>أولاً.</li>\n              <li><a href=\"https://css-tricks.com/reduced-test-cases/\">قلل مساحة البحث عن المشكلة</a>.</li>\n              <li>تذكر: كن دقيقاً</li>\n              <li>إسأل على IRC أو  <a href=\"http://stackoverflow.com\"> StackOverflow </a> و <a href=\"http://chat.stackoverflow.com/rooms/17/javascript\">ساحة المحادثات الخاصة به</a> أو أصدقائك.\n            </ol>\n          </div>\n\n          <div class=\"col-b\">\n                <section class=\"getinvolved\">\n              <h2 class=\"subhed\">يد المساعدة</h2>\n              <div class=\"task\" data-hashtag=\"#ask4help\">\n                <p>كلنا وصلنا إلى ما وصلنا إلية بالإعتماد على بعضنا. لا تكن خجولا, وأسال عما تريد. ولكن تذكر ان تقوم بعمل jsfiddle.</p>\n                <a href=\"#\" class=\"pledge\">نعم, سأفعل</a>\n                <div class=\"pledges\"><p>هنا بعض المطوريين الذين قرروا فعل ذلك أيضا:</p></div>\n              </div>\n             </section>\n          </div>\n        </section>\n    </article>\n\n    <article class=\"section\">\n        <div class=\"standout\" id=digdeep>\n            <h1 class=\"hed\">تعمق أكثر</h1>\n            <h2 class=\"subhed\">تعرف طريقك بوضوح. إذا هذا هو الوقت لتبدأ بالعمل</h2>\n        </div>\n        <section id=\"helpothers\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">ساعد الأخرين</h1>\n            <p>نحن جميعا نستفيد من بعضنا ونحتاج المساعدة من وقت إلى أخر, ومساعدة الأخرين تعمل على تثبيت المعلومات لديك,\n                        وتزيد من إدراكك وفهمك للتقنيات المختلفة.\n                        فى الأسفل ستجد مشاريع مفتوحة تحتاج إلى مساعدتك. تذكر ليس هناك مساهمة صغيرة, بل كل مساهمة لها قيمة.</p>\n            <h2 id=\"open_source_projects_worth_your_time\" class=\"subhed\">مشاريع مفتوحة المصدر تحتاج إلى وقتك</h2>\n\n            <ul>\n              <li><a href=\"http://github.com/h5bp/html5-boilerplate\">HTML5 Boilerplate</a> <span>- مشروع يساعدك على تطوير موقعك باستخدام افضل الممارسات.</span>\n              <li><a href=\"https://github.com/jquery/learn.jquery.com\">jQuery Learning Site</a> <span>- موقع تعليمى لمكتبة جافاسكريبت المشهورة jQuery.</span>\n              <li><a href=\"https://github.com/jquery/jquery-mobile\">jQuery Mobile</a> <span>- افضل الممارسات عن البرمجة للهواتف النقالة</span>\n              <li><a href=\"https://github.com/Modernizr/Modernizr\">Modernizr</a> <span>- مشروع يساعدك على الكشف عن التقنيات التى يدعمها المتصفح قبل تطبيقها.</span>\n              <li><a href=\"https://github.com/twbs/bootstrap\">Bootstrap</a> <span>- سجادة عمل لكل من HTML و CSS و JS تساعدك على بناء تطبيقات الويب بسرعة – مقدمة من تويتر.</span>\n              <li><a href=\"http://necolas.github.com/normalize.css/\">Normalize.css</a> <span>- مشروع لجعل كل المتصفحات تعرض مواقع الانترنت بنفس الطريقة.</span>\n              <li><a href=\"http://dojotoolkit.org/get-involved\">Dojo</a> <span>- سجادة عمل شاملة لتطوير تطبيقات الويب والهواتف النقالة.</span>\n              <li><a href=\"https://github.com/h5bp/lazyweb-requests/issues?state=open\">Lazyweb requests</a> <span>- ادوات وحلول من الرائع ان يمتلكها مطورى الويب.</span>\n            </ul>\n            <p>قم بإتباع خطوات<a href=\"#how_to_ask_for_help\"> &#8217;طلب المساعدة&#8216; </a> فى الأعلى وألق نظرة على <a href=\"http://addyosmani.com/blog/getting-involved-with-open-source/\">بودكاست Addy Osmani عن كيفية المشاركة</a> ! </p>\n\n          </div>\n\n          <div class=\"col-b\">\n            <section class=\"getinvolved\">\n              <h2 class=\"subhed\">شارك بخبرتك</h2>\n              <div class=\"task\" data-hashtag=\"#helpothers\">\n                <p>قراءة الكود العالى المستوى تؤدى إلى كتابة كود عالى المستوى, تصفح كود المشاريع الموضوعة هنا, وساعد على تطويرهم وجعلهم أفضل.</p>\n                <a href=\"#\" class=\"pledge\">نعم, سأفعل ذلك</a>\n                <div class=\"pledges\"><p>هنا بعض المطوريين الذين قرروا فعل ذلك أيضا:</p></div>\n              </div>\n            </section>\n          </div>\n        </section>\n\n        <section id=\"specs\" class=\"col-ab\">\n            <div class=\"col-a\">\n                <h1 class=\"hed\">أرسل تعليقاتك على المواصفات</h1>\n\n                <p>المواصفات  specifications (وهى عبارة عن وصف دقيق لما ينبغى ان تكون علية التقنية او لغة  البرمجة وكيف يتم استخدامها) تحدد وتنظم طريقة الأستخدام,\n                                ويتم وضعها من قبل فريق عمل Working Groups -WG من خلال محادثات مكثفة عن طريق البريد الإلكترونى.\n                                ولكن يبقى الإحتمال ان تقوم شركات متصفحات الويب بإنتاج متصفحات لا تتبع هذة المواصفات,\n                                وعندها يجب ان نقف نحن المطوريين ضد هذة البرامج ونقوم بإرسال feedback بكل خطأ نجدة فى هذة البرامج.</p>\n\n                <ul>\n                    <li>تعرف على <a href=\"http://diveintohtml5.info/past.html\">تاريخ الإنترنت</a>.</li>\n                    <li> إلقى نظرة على<a href=\"http://fantasai.inkedblade.net/weblog/2011/inside-csswg/\"> كيفية عمل مجموعات ال  CSS</a>.</li>\n                    <li>إشترك فى هذة القوائم البريدية لتتابع المشاركات والمناقشات التى تقود الويب:\n                        <ul class=\"resources\">\n                            <li><a href=\"http://lists.w3.org/Archives/Public/public-webapps/\">public-webapps</a> -  مناقشات تقنية عن تطوير تطبيقات الويب</li>\n                            <li><a href=\"http://lists.w3.org/Archives/Public/www-style/\">www-style</a> - مناقشات تقنية عن ال CSS </li>\n                            <li><a href=\"http://lists.whatwg.org/pipermail/whatwg-whatwg.org/\">whatwg</a> - القائمة البريدية ل Web Hypertext Application Technology Working Group </li>\n                            <li><a href=\"http://lists.w3.org/Archives/Public/public-html/\">public-html</a> - مناقشات تقنية حول HTML</li>\n                            <li><a href=\"http://lists.w3.org/Archives/Public/www-dom/\">www-dom</a> - مناقشات تقنية عن ال DOM </li>\n                            <li><a href=\"http://lists.w3.org/Archives/Public/public-fx/\">public-fx</a> - مناقشات حول القضايا التى توثر على ال CSS و SVG</li>\n                        </ul>\n                    </li>\n                    <li>إقرأ <a href=\"http://developers.whatwg.org/\">HTML5 Spec for developers</a> تم حذف ما لا يهم المطورين وتم تصميمها بطريقة جميلة</li>\n                    <li>أسهل طريقة لترسل تعليق او تبلغ عن خطا فى  <a href=\"http://www.whatwg.org/specs/web-apps/current-work/multipage/\">HTML specification</a> هى أن تقوم بتحديد الجزء الذى تريد ان تبلغ عنة ثم تكتب تعليقك فى الشريط اسفل الصفحة.</li>\n                    <li>\n                        تعرف على أخر القضايا حول ال HTML و  CSS عن طريق متابعة الحسابات الاتية\n                        <ul class=\"resources inverse_dir\">\n                            <li><a href=\"http://twitter.com/whatwg\">@whatwg</a></li>\n                            <li><a href=\"http://twitter.com/csscommits\">@csscommits</a></li>\n                        </ul>\n                    </li>\n                </ul>\n            </div>\n            <div class=\"col-b\">\n              <section class=\"getinvolved\">\n                <h2 class=\"subhed\">هل ستساهم؟</h2>\n                <div class=\"task\" data-hashtag=\"#feedback\">\n                  <p>نحن الذين نستخدم المواصفات,\n                                  فلماذا لا نساعد على عمل المواصفات التى نحب؟\n                                 دعنا نجعلها أفضل مما هى علية الأن.</p>\n                  <a href=\"#\" class=\"pledge\">نعم, سأفعل ذلك.</a>\n                  <div class=\"pledges\"><p>هنا بعض المطوريين الذين قرروا فعل ذلك أيضا:</p></div>\n                </div>\n              </section>\n            </div>\n        </section>\n\n        <section id=\"explore\" class=\"col-ab\">\n            <div class=\"col-a\">\n              <h1 class=\"hed\">إكتشف الإمكانيات الجديدة</h1>\n              <p>إذا كنت قد تعلمت الأساسيات,\n                          فهذا هو الوقت لتتعمق أكثر.\n                           هنا سوف نتعرف على Advanced CSS و الامكانيات الجديدة فى HTML ومستقبل هذة التقنيات.\n                          العديد من الأمكانيات متوفر دعمها الأن فى متصفحات الويب\n                           وإكتشاف هذة الإمكانيات والمميزات يساعدنا على دفع الويب إلى الأمام.</p>\n\n            <h2 id=\"examples_of_how_to_explore_features_well\" class=\"subhed\">أمثلة على أفضل الطرق للتعرف على الإمكانيات الجديدة</h2>\n            <ul class=\"inverse_dir inverse_align\">\n              <li><a href=\"http://perfectionkills.com/global-eval-what-are-the-options/\">Global <code>eval</code>: what are the options?</a> <span> - kangax</span>\n              <li><a href=\"http://nicolasgallagher.com/multiple-backgrounds-and-borders-with-css2/\">Multiple Backgrounds and Borders with CSS 2.1</a> <span> - Nicolas Gallagher</span>\n              <li><a href=\"http://nicolasgallagher.com/css-background-image-hacks/\">CSS background-image hacks</a> <span> - Nicolas Gallagher</span>\n              <li><a href=\"http://www.webdirections.org/blog/let-the-web-move-you-css3-animations-and-transitions/\">Let the Web move you — CSS3 Animations and Transitions</a> <span> - John Allsopp</span>\n              <li><a href=\"http://addyosmani.com/largescalejavascript/\">Patterns For Large-Scale JavaScript Application Architecture</a> <span> - Addy Osmani</span>\n              <li><a href=\"http://designfestival.com/the-cicada-principle-and-why-it-matters-to-web-designers/\">The Cicada Principle and why it matters to web designers</a> <span> - Alex Walker</span>\n              <li><a href=\"http://css-tricks.com/snippets/css/webkit-keyframe-animation-syntax/\">Keyframe animation syntax</a> <span> - Chris Coyier</span>\n              <li><a href=\"http://www.blog.highub.com/css/whats-new-in-css-selectors-level-4/\">What's new in CSS Selectors (Level 4)</a> <span> - Shi Chuan</span>\n              <li><a href=\"http://mathiasbynens.be/notes/touch-icons\">Everything you always wanted to know about touch icons</a> <span> - Mathias Bynens</span>\n              <li><a href=\"http://coding.smashingmagazine.com/2009/09/15/the-z-index-css-property-a-comprehensive-look/\">The z-index CSS Property: A Comprehensive Look</a> <span> - Louis Lazaris</span>\n            </ul>\n\n            <h2 id=\"cool_ideas_to_explore_more\" class=\"subhed\">مميزات رائعة لتكتشفها ( وربما تكتب عنها )</h2>\n\n            <p>المتصفحات تضيف مميزات CSS دائما.\n                        ونحن نكره الأوامر الخاصة بكل متصفح vendor prefixes لذلك نرسل تعليقاتنا عليها دائما وأنها لا تناسب عملنا.\n                        لذلك تشجع ان تجرب كل ميزه جديدة وترسل تعليقك عليها.\n                        وهذة نظرة على <a href=\"http://peter.sh/experiments/vendor-prefixed-css-property-overview/\">vendor-prefixed CSS property</a>,\n                        كتبها Peter Beverloo, وفيها العديد من اوامر ال CSS التى تحت التجربة - وكثير منها ليست معروفة وليست مفهومة عند الكثير.\n                        يمكنك الكتابة عنها لتعلمها وتبسطها للمطوريين الاخرين - وهناك خواص أخرى مثل:\n\n              <ul class=\"inverse_dir inverse_align\">\n                <li><a href=\"https://developer.mozilla.org/En/CSS/%3Achecked\">The :checked selector</a> / <a href=\"http://dev.w3.org/csswg/css3-images/#object-fit\">object-fit</a>  / <a href=\"https://developer.mozilla.org/en/CSS/background-clip\">background-clip</a> / <a href=\"https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html\">fx blur css filter</a> / <a href=\"http://dropshado.ws/post/1015351370/webkit-line-clamp\">-webkit-line-clamp</a> / <a href=\"https://developer.mozilla.org/en/CSS/text-overflow\">text-overflow</a> / <a href=\"https://developer.mozilla.org/En/CSS/Box-sizing\">box-sizing</a> / <a href=\"https://developer.mozilla.org/en/CSS3_Columns\">CSS columns</a></li>\n                <li><code>history.pushState()</code>, HTML5 input <code>checkValidity()</code>, <code>getClientRects</code> / <code>getBoundingClientRect</code>, WebKit's <a href=\"http://developer.apple.com/library/safari/#documentation/DataManagement/Reference/DOMWindowAdditionsReference/DOMWindowAdditions/DOMWindowAdditions.html\">ConvertPointFromPageToNode</a>\n                <li><a href=\"http://www.w3.org/TR/css3-gcpm/\">CSS Generated Content for Paged Media Module (GCPM)</a>\n                <li>Differences between <code>word-wrap</code>, <code>word-break</code>, and <code>white-space</code>\n                <li>Harmony features like <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:let\">let</a> / <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:block_scoped_bindings\">block-scoped bindings</a> / block functions /  <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:destructuring\">destructuring</a> / <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:rest_parameters\">rest parameters</a> / <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:parameter_default_values\">default param values</a>.\n                <li><a href=\"http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html\">Web Components Explained (very early draft)</a>\n\n                <li><strong>Any features from these presentations:</strong>\n                  <ul>\n                    <li><a href=\"http://vimeo.com/32135328\">The Future of CSS</a> <span>- Tab Atkins on what to expect from CSS in the future.</span>\n                    <li><a href=\"http://infrequently.org/11/fronteers/fronteers.html\">Data, Semantics, and the Process of Progress </a> <span>- browser evolution, Component Model, MDV</span>\n                    <li><a href=\"http://infrequently.org/11/ldnjs/ldnjs.html\">[JS|DOM].next()</a> <span>- Alex Russell on the next version of ECMAScript.</span>\n                    <li><a href=\"http://lea.verou.me/css3-secrets/\">CSS3 Secrets</a> <span>- an interactive presentation on advanced CSS3 functionality.</span>\n                    <li><a href=\"http://nimbu.in/w3conf/\">The Future of Layouts in CSS</a> <span>- and how emerging specs will add proper layout control to CSS</span>\n                    <li><a href=\"http://mezzoblue.com/presentations/2011/fowd/FOWD.pdf\">The Future of CSS</a> <span>- an overview of a number of surfacing CSS features.</span>\n\n                </ul>\n              </ul>\n\n            </div>\n            <div class=\"col-b\">\n                  <section class=\"getinvolved\">\n                <h2 class=\"subhed\">إكتشف المجهول</h2>\n                <div class=\"task\" data-hashtag=\"#explore\">\n                  <p>الطريقة الوحيدة لدفع الويب إلى الأمام هى تعلم التقنيات المتقدمة ومن ثم إستخدامها.\n                                  وستستمتع بتعلم هذة التقنيات كثيراً.</p>\n                  <a href=\"#\" class=\"pledge\">نعم سأفعل ذلك</a>\n                  <div class=\"pledges\"><p>هنا بعض المطوريين الذين قرروا فعل ذلك أيضا:</p></div>\n                </div>\n             </section>\n          </div>\n        </section>\n\n\n        <section id=\"write\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">أكتب</h1>\n            <p>أنشر ما تعلمتة ولا تخف من إرتكاب الأخطاء.\n                        أنشر على مدونتك و أحرص على ان تكون مقالاتك محدثة دائما.\n                        وقم بعمل مناقشات مع قراء مدونتك وعلمهم وتعلم منهم.</p>\n\n            <p>تعليم الناس هو طريقة جيدة للتعلم ولتثبيت المعلومات.\n                        لذلك فأنت تستفيد انت ايضا عندما تعلم الناس</p>\n\n            <h2 id=\"what_should_you_start_to_learn_about\" class=\"subhed\">ما الذى يجب ان تكتب عنة؟</h2>\n\n            <p>أشياء يمكن ان تعلمها للناس: هنا ستجد أفكار جيدة</p>\n\n            <ul>\n                <li>لماذا وُجدت هذة التاج <code>&lt;br&gt;</code> و <code>&lt;hr&gt;</code>؟</li>\n                <li>كيف تقوم بعمل slideshow بأقل قدر ممكن من الكود ؟</li>\n                <li>ما هو ال DOM ؟ ولماذا وُجد ؟</li>\n                <li>أنظر كيف يقوم المتصفح بتطبيق أى واحدة من ال  CSS property , وقارن هذا مع ال CSS specifications </li>\n                <li>كيف تقوم المواقع المشهورة بعمل صفحتها الرئيسية .</li>\n                <li>كيف يمكنك إصلاح أحد أخطاء المواقع الكبيرة (مثل: وقت كبير فى التحميل - خطا فى الجافاسكربت - او أخرى )</li>\n                <li>خذ Demo مشهورة و أشرحها بطريقة مختلفة او اشرحها هى نفسها</li>\n                <li>قم بعمل تلخيص للأفكار التى تدور فى الويب مؤخراً.</li>\n                <li>أكتب عن خبرتك فى المشاريع المفتوحة المصدر.</li>\n                <li>كيف يمكن لل\n                                <a href=\"http://www.catswhocode.com/blog/8-css-preprocessors-to-speed-up-development-time\"> CSS preprocessor </a>\n                                أن تؤدى إلى اخطاء فى الكود, إذا لم يتم التعامل معها بطريقة صحيحة\n                                </li>\n                <li>إذا كانت لغتك الأم غير الإنجليزية:\n                <ul class=\"resources\">\n                  <li>ترجم بعض المقالات المهمة والمشهورة عن تطوير وبرمجة الويب.</li>\n                  <li>وضح الأشياء الغامضة او الغير معروفة فى ال specifications</li>\n                </ul>\n              </li>\n            </ul>\n          </div>\n          <div class=\"col-b\">\n            <section class=\"getinvolved\">\n              <h2 class=\"subhed\">أكتب</h2>\n              <div class=\"task\" data-hashtag=\"#write\">\n                <p>ولا تلتفت إلى عدد القراء او عدد المتابعين لك على تويتر - قدم ما تعلمتة وسيكون هناك من يستفيد</p>\n                <a href=\"#\" class=\"pledge\">نعم, سأفعل ذلك</a>\n                <div class=\"pledges\"><p>هنا بعض المطوريين الذين قرروا فعل ذلك أيضا:</p></div>\n              </div>\n            </section>\n          </div>\n        </section>\n        <section id=\"filebugs\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">بلغ عن الأخطاء</h1>\n            <p>يجب على شركات المتصفحات أن تعالج أخطاء المتصفحات بجدية اكثر, وعلينا ان نساعدهم فى ذلك.</p>\n            <ul>\n              <li><a href=\"http://coding.smashingmagazine.com/2011/09/07/help-the-community-report-browser-bugs/\">ساعد مجتمع الويب: بلغ عن أخطاء المتصفحات</a> - كتبه  Lea Verou</li>\n              <li><a href=\"http://ejohn.org/blog/a-web-developers-responsibility/\">مسئولية مطوري الويب</a> - كتبه   John Resig</li>\n              <li><a href=\"http://a11ybugs.org/\">Help prioritize browser accessibility bugs</a> - كتبه   Vlad Alexander</li>\n              <li>\n                <p>المواقع الخاصة بأخطاء المتصفحات - ساهم فى حل خطا موجود بالفعل أو بلغ عن خطأ جديد:</p>\n                <ul class=\"resources\">\n                  <li><a href=\"https://bugzilla.mozilla.org/\">Mozilla's bugzilla</a></li>\n                  <li><a href=\"https://bugs.webkit.org/\">WebKit bugs</a></li>\n                  <li><a href=\"http://crbug.com/\">Chrome bugs</a></li>\n                  <li><a href=\"http://www.opera.com/support/bugs/\">Opera bugs</a></li>\n                  <li><a href=\"https://connect.microsoft.com/site/sitehome.aspx?SiteID=136\">Help IE</a></li>\n                </ul>\n              </li>\n            </ul>\n          </div>\n          <div class=\"col-b\">\n            <section class=\"getinvolved\">\n              <h2 class=\"subhed\">  إقضى على مشاكل المتصفحات</h2>\n              <div class=\"task\" data-hashtag=\"#filebugs\">\n                <p>هذة هى أسرع طريقة لتحسيين اداء المتصفحات -\n                                عن طريق التبليغ عن المشاكل وحلها.\n                                هذة العملية لا تستغرق بضع دقائق, ويمكن لأى شخص القيام بها.</p>\n                <a href=\"#\" class=\"pledge\">نعم, سأشارك فى ذلك</a>\n                <div class=\"pledges\"><p>هنا بعض المطوريين الذين قرروا فعل ذلك أيضا:</p></div>\n              </div>\n            </section>\n          </div>\n        </section>\n    </article>\n    <article class=\"section\">\n      <div class=\"standout\" id=virtuoso>\n        <h1 class=\"hed\">مبدع!</h1>\n        <h2 class=\"subhed\">لديك خبرة طويلة, وأنت الأن محترف فى تقنيات الويب - إذا دعنا نقترح عليك بعض الأشياء</h2>\n      </div>\n      <section id=\"hack\" class=\"col-ab\">\n        <div class=\"col-a\">\n          <h1 class=\"hed\">\n                  <a href=\"http://ar.wikipedia.org/wiki/%D9%87%D8%A7%D9%83%D8%B1#.D8.A7.D9.84.D8.AE.D9.84.D8.A7.D9.81_.D8.AD.D9.88.D9.84_.D8.AA.D8.B9.D8.B1.D9.8A.D9.81_.D8.A7.D9.84.D9.87.D8.A7.D9.83.D8.B1\">هاك</a></h1>\n          <p>إدفع الويب إلى أقصى حدودة.\n                  هاك على CSS او advanced HTML  او  JavaScript\n                  او the browser's rendering engine.\n                  ادخل على مواقع مثل  github\n                  , اختر مشروع وتفحص الكود جيدا وتعلم منة ثم ضع لمستك انت.\n                   هيا نجعل الويب مكان رائع -  هناك طرق كثيره لفعل ذلك:</p>\n          <h2 id=\"contribute_to_browsers\" class=\"subhed\">ساهم فى تطوير المتصفحات</h2>\n          <ul>\n            <li>ساعد فى تطوير أدوات المطوريين مثل\n                        <a href=\"http://trac.webkit.org/wiki/WebInspector\">WebKit Inspector</a>\n                        و  <a href=\"https://github.com/operasoftware/dragonfly/\">Dragonfly</a>.\n            لقد تم برمجتهم بإستخدام  HTML و CSS و JS\n                        لذلك فأنت لا تحتاج انت تكون مبرمج ++C لتشارك فى تطويرهم.</li>\n            <li><a href=\"https://developer.mozilla.org/en/Gecko_BugAThon\">قلل من ال  test cases لموزيلا.</a></li>\n            <li>هاك على Gecko\n              <ul>\n                <li>إقرأ دليل المطوريين  <a href=\"https://developer.mozilla.org/En/Developer_Guide\">لتبدأ فى تطوير Gecko.</a>.\n                <li><a href=\"https://bugzilla.mozilla.org/buglist.cgi?quicksearch=%22[mentor%3D%22&list_id=1800469\">قائمة ببعض اهم الأخطاء فى firefox و Gecko .</a>\n                <li>إشترك فى المحادثات على غرفتى  introduction# و developers# على  <a href=\"#mozilla_irc\">Mozilla's IRC server</a>\n              </ul>\n            <li>هاك على  Webkit\n              <ul>\n                <li><a href=\"http://dev.chromium.org/developers/contributing-to-webkit\">دليل من جوجل للمساهمة فى تطوير Webkit.</a>\n              </ul>\n          </ul>\n\n          <h2 id=\"contribute_to_testsuites\" class=\"subhed\">ساهم فى\n                  <a href=\"http://en.wikipedia.org/wiki/Test_suite\">سلاسل الإختبارات</a></h2>\n\n          <p><a href=\"http://en.wikipedia.org/wiki/Test_case\">الإختبارات</a> هى شئ أساسى عند وضع معايير الويب وتطوير المتصفحات.\n                   ومن خلالها نتأكد من تعامل المتصفحات مع التقنيات بنفس الطريقة ام كل متصفح مختلف عن الأخر.\n                 حالياً, سلاسل إختبارات   W3C ليس لديها إختبارات بالقدر التى تحتاجة.\n                  هذة الإختبارات تكتب بلغات تطوير الويب الأساسية HTML  و CSS و JS.</p>\n\n          <ul class=\"inverse_dir inverse_align\">\n            <li>Get overviews of the\n              <a href=\"http://www.w3.org/2008/webapps/wiki/Testing\">w3c webapps test suite</a>, the\n              <a href=\"http://www.w3.org/html/wg/wiki/Testing\">w3c HTML5 test suite</a>,\n              and the <a href=\"http://wiki.csswg.org/test\">CSSWG test suite</a>.\n            </li>\n            <li>Look into <a href=\"http://www.w3.org/html/wg/wiki/Testing#New_tests\">upstreaming some existing tests</a> into the W3C Test suite.</li>\n            <li>Upstream <a href=\"http://trac.webkit.org/browser/trunk/LayoutTests\">WebKit&#8217;s LayoutTests</a>. <span>Also see the LayoutTests <a href=\"http://www.webkit.org/blog/1452/layout-tests-theory/\">theory</a> & <a href=\"http://www.webkit.org/blog/1456/layout-tests-practice/\">practice</a>.</span></li>\n            <li>Upstream <a href=\"https://developer.mozilla.org/en/Mochitest\">Mozilla&#8217;s Mochitests</a>.</li>\n            <li>Join the conversation on <a href=\"http://lists.w3.org/Archives/Public/public-webapps-testsuite/\">public-webapps-testsuite</a>, <a href=\"http://lists.w3.org/Archives/Public/public-html-testsuite/\">public-html-testsuite</a>, and <a href=\"http://lists.w3.org/Archives/Public/public-css-testsuite/\">public-css-testsuite</a>.</li>\n            <li>Contribute to HTML5 Audio on <a href=\"http://areweplayingyet.org\">the AreWePlayingYet? test suite</a>.</li>\n          </ul>\n\n\n          <h2 id=\"contribute_to_specs\" class=\"subhed\">ساهم فى المواصفات &nbsp; specifications</h2>\n          <ul>\n            <li>راجع على الأخطاء الموجودة على  <a href=\"http://www.w3.org/Bugs/Public/\">W3C bugzilla</a> <span>- وتعلم <a href=\"http://wiki.whatwg.org/wiki/Bugzilla_conventions\">Bugzilla conventions</a>.</span>\n            <li>شارك فى محادثات  <a href=\"http://www.whatwg.org/mailing-list\">WHATWG</a> / <a href=\"http://lists.w3.org/Archives/Public/public-webapps/\">public-webapps</a> / <a href=\"http://lists.w3.org/Archives/Public/www-style/\">www-style</a> / <a href=\"http://lists.w3.org/Archives/Public/public-fx/\">public-fx</a>.</li>\n            <li><a href=\"http://dev.chromium.org/developers/how-tos/make-a-web-standards-proposal\">قم بكتابة إقتراحات لمعايير الويب.</a>. <span>(هنا ستجد كيفية فعل ذلك.)</span>\n            <li><a href=\"http://wiki.whatwg.org/wiki/How_to_write_a_spec\">أكتب بعض المواصفات. </a> </li>\n          </ul>\n          <h2 id=\"contribute_to_validators\" class=\"subhed\">ساهم فى\n                  <a href=\"http://en.wikipedia.org/wiki/Validator\">أدوات التحقق من صحة الكود</a></h2>\n          <ul class=\"inverse_dir inverse_align\">\n            <li>\n              <a href=\"http://validator.nu/\">HTML Validator</a> <span>needs some developer lovin', deets at <a href=\"https://github.com/h5bp/lazyweb-requests/issues/18\">lazyweb-reqs/18</a></span>\n            <li>\n              <a href=\"http://lists.w3.org/Archives/Public/www-validator-css/\">CSS Validator</a> <span>can always use some help. hop on that mailing list!</span>\n            <li>\n              <a href=\"https://bitbucket.org/annevk/webvtt\">WebVTT</a> <span>a video subtitling format, is an active area of standards interest</span>\n          </ul>\n        </div>\n        <div class=\"col-b\">\n          <section class=\"getinvolved\">\n            <h2 class=\"subhed\">أترك بصمتك</h2>\n            <div class=\"task\" data-hashtag=\"#hack\">\n              <p>طور بعض الأدوات.\n                          تفحص وأختبر المشاريع.\n                          شارك فى تطوير المتصفحات أو أدوات التحقق من صحة الكود أو المواصفات أو <a href=\"#open_source_projects_worth_your_time\">المشاريع المفتوحة المصدر</a>.</p>\n              <a href=\"#\" class=\"pledge\">سأشارك بالتأكيد</a>\n              <div class=\"pledges\"><p>هنا بعض المطوريين الذين قرروا فعل ذلك أيضا:</p>\n            </div>\n          </section>\n        </div>\n      </section>\n    </article>\n\n\n\n    <footer class=\"doc\">\n\n      <p class=\"subhed summary\">\n      يمكنك أن تجعل الويب رائع كما تحب .</br>\n                شركات المتصفحات والعاملين على معايير الويب وأخرون يحتاجون إلى مشاراكاتك ومساهماتك.\n                <br>معاً نستطيع أن ندفع الويب إلى الأمام.\n\n      </p>\n\n      <img src=\"/img/pugerton.png\" alt=\"Pugerton\">\n\n      <p class=\"subhed\">قام بكتباتة - بكل حب</p>\n\n      <ul class=\"builders\">\n          <li><a href=\"https://twitter.com/wilto\"><img src=\"https://pbs.twimg.com/profile_images/477441227986444289/KHCUqTis_normal.png\" alt=\"Mat Marquis\"> <b>Mat</b> Marquis</a>\n          <li><a href=\"https://twitter.com/aaronforsander\"><img src=\"https://pbs.twimg.com/profile_images/461528075788763138/c7ONSIRm_normal.jpeg\" alt=\"Aaron Forsander\"> <b>Aaron</b> Forsander</a>\n          <li><a href=\"https://twitter.com/connor\"><img src=\"https://pbs.twimg.com/profile_images/526185574039031808/IpDbRAX5_normal.jpeg\" alt=\"Connor Montgomery\"> <b>Connor Montgomery</b></a>\n          <li><a href=\"https://twitter.com/paul_irish\"><img src=\"https://pbs.twimg.com/profile_images/420826194083213312/CP1RmLa3_normal.jpeg\" alt=\"Paul Irish\"> <b>Paul</b> Irish</a>\n          <li><a href=\"https://twitter.com/divya\"><img src=\"https://pbs.twimg.com/profile_images/550530231853776897/kni4F8oM_normal.png\" alt=\"Diviya Manian\"> <b>Divya</b> Manian</a>\n          <li><a href=\"https://twitter.com/necolas\"><img src=\"https://pbs.twimg.com/profile_images/529444560179449857/eKdCJhvp_normal.jpeg\" alt=\"Nicolas Gallagher\"> <b>Nicolas</b> Gallagher</a>\n          <li><a href=\"https://twitter.com/addyosmani\"><img src=\"https://pbs.twimg.com/profile_images/422476220442234880/jlx9HMtr_normal.jpeg\" alt=\"Addy Osmani\"> <b>Addy</b> Osmani</a>\n      </ul>\n      <p class=\"others\">&amp; <a href=\"https://github.com/h5bp/movethewebforward/contributors\"><span>وكل هؤلاء المطوريين الرائعين.</span>.</a></p>\n                <p>قام بالترجمة  - <a href=\"https://plus.google.com/u/0/110896024219505135276/about\">مروان عبد المنعم</a> •</p>\n          <p>قامت بعمل صور الديناصورات - <a href=\"http://dribbble.com/deathbearbrown\">Sue Lockwood</a> •</p>\n                <p><a href=\"https://github.com/h5bp/movethewebforward\">قدم مساهمتك فى هذا المشروع</a></p>\n    </footer>\n    <script>\n        window._gaq=[['_setAccount','UA-17904194-2'],['_trackPageview']];\n        (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];\n        g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';\n        s.parentNode.insertBefore(g,s)}(document,'script'));\n    </script>\n</body>\n</html>\n"
  },
  {
    "path": "avatars.php",
    "content": "<?php\n\n// Enable errors for easy debugging.\nerror_reporting(E_ALL);\nini_set('display_errors', '1');\n\n// Configurable stuff.\ndefine('URL', 'http://search.twitter.com/search.json');\ndefine('SEARCH_PREFIX', '(ivegotmybluebeanieonnowwhat.com OR movethewebforward.com OR movethewebforward.org) AND ');\ndefine('RPP', 100);\n\n// Hashtags to search twitter for.\n$queries = array(\n  \"#learn\",\n  \"#ask4help\",\n  \"#helpothers\",\n  \"#feedback\",\n  \"#explore\",\n  \"#write\",\n  \"#filebugs\",\n  \"#hack\"\n);\n\n// Don't let random scallywags run this script.\nif ((isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] !== '127.0.0.1') || PHP_SAPI !== 'cli')\n  die('☹');\n\n// Search twitter, return full json_decode()'d response.\nfunction search($query, $page = 1) {\n  $url = URL . '?' . http_build_query(array(\n    'q' => SEARCH_PREFIX . $query,\n    'rpp' => RPP,\n    'page' => $page\n  ));\n\n  $ch = curl_init($url);\n  curl_setopt($ch, CURLOPT_NOBODY, 0);\n  curl_setopt($ch, CURLOPT_HEADER, 0);\n  curl_setopt($ch, CURLOPT_USERAGENT, 'movethewebforward.org');\n  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);\n  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\n\n  $response = curl_exec($ch);\n  $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);\n  curl_close($ch);\n\n  if ($status == 200) {\n    return json_decode($response);\n  }\n  else {\n    die(\"Twitter error: \" . $status);\n  }\n}\n\n// Get all results for a query.\nfunction getAll($query) {\n  $page = 0;\n  $avatars = array();\n\n  do {\n    $results = search($query, ++$page);\n\n    foreach ($results->results as $result) {\n      $avatars[$result->from_user] = $result->profile_image_url;\n    }\n  }\n  while (count($results->results) == RPP);\n\n  return $avatars;\n}\n\n// Merge new avatars into our file of existing avatars.\n$avatars = json_decode(file_get_contents('avatars.json'));\n\nforeach ($queries as $query) {\n  $avatars->$query = array_merge((array)$avatars->$query, getAll($query));\n}\n\nfile_put_contents('avatars.json', json_encode($avatars));\n"
  },
  {
    "path": "build/build.xml",
    "content": "<?xml version=\"1.0\"?>\n<!DOCTYPE project>\n<project name=\"Boilerplate Build\" default=\"build\" basedir=\"../\"> <!-- one back since we're in build/ -->\n\n\n    <!-- Load in Ant-Contrib to give us access to some very useful tasks! -->\n    <!-- the .jar file is located in the tools directory -->\n    <taskdef resource=\"net/sf/antcontrib/antlib.xml\">\n        <classpath>\n            <pathelement location=\"${basedir}/build/tools/ant-contrib-1.0b3.jar\"/>\n        </classpath>\n    </taskdef>\n\n    <!-- load shell environment -->\n    <property environment=\"ENV\" />\n\n    <!-- load property files -->\n    <property file=\"build/config/project.properties\"/>\n    <property file=\"build/config/default.properties\"/>\n\n    <!-- merge the stylesheet properties -->\n    <var name=\"stylesheet-files\" value=\"${file.default.stylesheets}, ${file.stylesheets}\"/>\n\n    <!-- merge the pages properties -->\n    <var name=\"page-files\" value=\"${file.pages}, ${file.pages.default.include}\"/>\n\n    <!-- Test for Ant Version Delete this task and all instances of overwrite='no' if you can't upgrade to 1.8.2-->\n    <fail message=\"All features of the build script require Ant version 1.8.2. Please upgrade to 1.8.2 or remove all instances of 'overwrite=no' (and this fail task) from the build script to continue\">\n        <condition>\n            <not>\n                <contains string=\"${ant.version}\" substring=\"1.8.2\"/>\n            </not>\n        </condition>\n    </fail>\n\n    <!--\n    *************************************************\n    * BASE TARGETS                                  *\n    *************************************************\n    -->\n    <target name=\"basics\">\n    <if>\n        <equals arg1=\"${env}\" arg2=\"dev\"/>\n        <then>\n            <!-- Build a dev environment -->\n            <echo message=\"Building a Development Environment...\"/>\n            <antcall target=\"-basics.dev\"/>\n        </then>\n\n        <elseif>\n            <equals arg1=\"${env}\" arg2=\"test\"/>\n            <then>\n                <!-- Build a test environment -->\n                <echo message=\"Building a Test Environment...\"/>\n                <antcall target=\"-basics.test\"/>\n            </then>\n        </elseif>\n\n        <else>\n            <!-- Build a production environment -->\n            <echo message=\"Building a Production Environment...\"/>\n            <antcall target=\"-basics.production\"/>\n        </else>\n    </if>\n    </target>\n\n\n    <target name=\"text\">\n    <if>\n        <equals arg1=\"${env}\" arg2=\"dev\"/>\n        <then>\n            <!-- Build a dev environment -->\n            <echo message=\"Building a Development Environment...\"/>\n            <antcall target=\"-text.dev\"/>\n        </then>\n\n        <elseif>\n            <equals arg1=\"${env}\" arg2=\"test\"/>\n            <then>\n                <!-- Build a test environment -->\n                <echo message=\"Building a Test Environment...\"/>\n                <antcall target=\"-text.test\"/>\n            </then>\n        </elseif>\n\n        <else>\n            <!-- Build a production environment -->\n            <echo message=\"Building a Production Environment...\"/>\n            <antcall target=\"-text.production\"/>\n        </else>\n    </if>\n    <antcall target=\"-imgcopy\"/>\n    </target>\n\n\n    <target name=\"buildkit\">\n    <if>\n        <equals arg1=\"${env}\" arg2=\"dev\"/>\n        <then>\n            <!-- Build a dev environment -->\n            <echo message=\"Building a Development Environment...\"/>\n            <antcall target=\"-buildkit.dev\"/>\n        </then>\n\n        <elseif>\n            <equals arg1=\"${env}\" arg2=\"test\"/>\n            <then>\n                <!-- Build a test environment -->\n                <echo message=\"Building a Test Environment...\"/>\n                <antcall target=\"-buildkit.test\"/>\n            </then>\n        </elseif>\n\n        <else>\n            <!-- Build a production environment -->\n            <echo message=\"Building a Production Environment...\"/>\n            <antcall target=\"-buildkit.production\"/>\n        </else>\n    </if>\n    </target>\n\n\n    <target name=\"build\">\n    <if>\n        <equals arg1=\"${env}\" arg2=\"dev\"/>\n        <then>\n            <!-- Build a dev environment -->\n            <echo message=\"Building a Development Environment...\"/>\n            <antcall target=\"-build.dev\" />\n        </then>\n\n        <elseif>\n            <equals arg1=\"${env}\" arg2=\"test\"/>\n            <then>\n                <!-- Build a test environment -->\n                <echo message=\"Building a Test Environment...\"/>\n                <antcall target=\"-build.test\" />\n            </then>\n        </elseif>\n\n        <else>\n            <!-- Build a production environment -->\n            <echo message=\"Building a Production Environment...\"/>\n            <antcall target=\"-build.production\" />\n        </else>\n    </if>\n    </target>\n\n\n    <target name=\"minify\">\n    <if>\n        <equals arg1=\"${env}\" arg2=\"dev\"/>\n        <then>\n            <!-- Build a dev environment -->\n            <echo message=\"Building a Development Environment...\"/>\n            <antcall target=\"-minify.dev\"/>\n        </then>\n\n        <elseif>\n            <equals arg1=\"${env}\" arg2=\"test\"/>\n            <then>\n                <!-- Build a test environment -->\n                <echo message=\"Building a Test Environment...\"/>\n                <antcall target=\"-minify.test\"/>\n            </then>\n        </elseif>\n\n        <else>\n            <!-- Build a production environment -->\n            <echo message=\"Building a Production Environment...\"/>\n            <antcall target=\"-minify.production\"/>\n        </else>\n    </if>\n    </target>\n\n    <target name=\"clean\" depends=\"-clean\"/>\n\n\n\n    <!-- JSLint target, run separately -->\n    <target name=\"jslint\">\n      <apply dir=\"${dir.source}/${dir.js}\" executable=\"java\" parallel=\"false\" failonerror=\"true\">\n            <fileset dir=\"./${dir.source}/\">\n        <include name=\"**/${dir.js}/*.js\"/>\n        <exclude name=\"**/*.min.js\"/>\n        <exclude name=\"**/${dir.js.libs}/\"/>\n        <exclude name=\"**/${dir.publish}/\"/>\n          </fileset>\n            <arg value=\"-jar\" />\n            <arg path=\"./${dir.build.tools}/${tool.rhino}\" />\n            <arg path=\"./${dir.build.tools}/${tool.jslint}\" />\n            <srcfile/>\n            <arg value=\"${tool.jslint.opts}\" />\n        </apply>\n        <echo>JSLint Successful</echo>\n    </target>\n\n\n    <!-- JSHint target, run separately -->\n    <target name=\"jshint\">\n      <apply dir=\"${dir.source}/${dir.js}\" executable=\"java\" parallel=\"false\" failonerror=\"true\">\n            <fileset dir=\"./${dir.source}/\">\n        <include name=\"**/${dir.js}/*.js\"/>\n        <exclude name=\"**/*.min.js\"/>\n        <exclude name=\"**/${dir.js.libs}/\"/>\n        <exclude name=\"**/${dir.publish}/\"/>\n          </fileset>\n            <arg value=\"-jar\" />\n            <arg path=\"./${dir.build.tools}/${tool.rhino}\" />\n            <arg path=\"./${dir.build.tools}/${tool.jshint}\" />\n            <srcfile/>\n            <arg value=\"${tool.jshint.opts}\" />\n        </apply>\n        <echo>JSHint Successful</echo>\n    </target>\n\n    <!-- CSSLint target, run separately -->\n    <target name=\"csslint\">\n        <apply dir=\"${dir.source}/${dir.css}\" executable=\"java\" parallel=\"false\" failonerror=\"true\">\n            <fileset dir=\"./${dir.source}/\">\n                <include name=\"**/${dir.css}/*.css\"/>\n                <exclude name=\"**/*.min.css\"/>\n                <exclude name=\"**/${dir.publish}/\"/>\n            </fileset>\n            <arg value=\"-jar\" />\n            <arg path=\"./${dir.build.tools}/${tool.rhino}\" />\n            <arg path=\"./${dir.build.tools}/${tool.csslint}\" />\n            <srcfile/>\n            <arg value=\"${tool.csslint.opts}\" />\n        </apply>\n        <echo>CSSLint Successful</echo>\n    </target>\n\n    <!--\n    *************************************************\n    * BUILD TARGETS                                 *\n    *************************************************\n    -->\n\n    <!-- Target: basics -->\n    <target name=\"-basics.dev\"\n            depends=\"-intro,\n                     -copy\"/>\n\n    <target name=\"-basics.test\"\n            depends=\"-intro,\n                     -usemin,\n                     -js.all.minify,\n                     -js.main.concat,\n                     -js.mylibs.concat,\n                     -js.scripts.concat,\n                     -css,\n                     -manifest,\n                     -copy\"/>\n\n    <target name=\"-basics.production\"\n            depends=\"-intro,\n                     -usemin,\n                     -js.all.minify,\n                     -js.main.concat,\n                     -js.mylibs.concat,\n                     -js.scripts.concat,\n                     -css,\n                     -manifest,\n                     -copy\"/>\n\n    <!-- Target: text -->\n    <target name=\"-text.dev\"\n            depends=\"-intro,\n                     -copy\"/>\n\n    <target name=\"-text.test\"\n            depends=\"-intro,\n                     -usemin,\n                     -js.all.minify,\n                     -js.main.concat,\n                     -js.mylibs.concat,\n                     -js.scripts.concat,\n                     -css,\n                     -manifest,\n                     -htmlclean,\n                     -copy\"/>\n\n    <target name=\"-text.production\"\n            depends=\"-intro,\n                     -usemin,\n                     -js.all.minify,\n                     -js.main.concat,\n                     -js.mylibs.concat,\n                     -js.scripts.concat,\n                     -css,\n                     -manifest,\n                     -htmlclean,\n                     -copy\"/>\n\n    <!-- Target: buildkit -->\n    <target name=\"-buildkit.dev\"\n            depends=\"-intro,\n                     -imagespng,\n                     -imagesjpg,\n                     -copy\"/>\n\n    <target name=\"-buildkit.test\"\n            depends=\"-intro,\n                     -usemin,\n                     -js.all.minify,\n                     -js.main.concat,\n                     -js.mylibs.concat,\n                     -js.scripts.concat,\n                     -css,\n                     -manifest,\n                     -htmlbuildkit,\n                     -imagespng,\n                     -imagesjpg,\n                     -copy\"/>\n\n    <target name=\"-buildkit.production\"\n            depends=\"-intro,\n                     -usemin,\n                     -js.all.minify,\n                     -js.main.concat,\n                     -js.mylibs.concat,\n                     -js.scripts.concat,\n                     -css,\n                     -manifest,\n                     -htmlbuildkit,\n                     -imagespng,\n                     -imagesjpg,\n                     -copy\"/>\n\n    <!-- Target: build -->\n    <target name=\"-build.dev\"\n            depends=\"-intro,\n                     -imagespng,\n                     -imagesjpg,\n                     -copy\"/>\n\n    <target name=\"-build.test\"\n            depends=\"-intro,\n                     -usemin,\n                     -js.all.minify,\n                     -js.main.concat,\n                     -js.mylibs.concat,\n                     -js.scripts.concat,\n                     -css,\n                     -manifest,\n                     -htmlclean,\n                     -imagespng,\n                     -imagesjpg,\n                     -copy\"/>\n\n    <target name=\"-build.production\"\n            depends=\"-intro,\n                     -usemin,\n                     -js.all.minify,\n                     -js.main.concat,\n                     -js.mylibs.concat,\n                     -js.scripts.concat,\n                     -css,\n                     -manifest,\n                     -htmlclean,\n                     -imagespng,\n                     -imagesjpg,\n                     -copy\"/>\n\n    <!-- Target: minify -->\n    <target name=\"-minify.dev\"\n            depends=\"-intro,\n                     -imagespng,\n                     -imagesjpg,\n                     -copy\"/>\n\n    <target name=\"-minify.test\"\n            depends=\"-intro,\n                     -usemin,\n                     -js.all.minify,\n                     -js.main.concat,\n                     -js.mylibs.concat,\n                     -js.scripts.concat,\n                     -css,\n                     -manifest,\n                     -htmlcompress,\n                     -imagespng,\n                     -imagesjpg,\n                     -copy\"/>\n\n    <target name=\"-minify.production\"\n            depends=\"-intro,\n                     -usemin,\n                     -js.all.minify,\n                     -js.main.concat,\n                     -js.mylibs.concat,\n                     -js.scripts.concat,\n                     -css,\n                     -manifest,\n                     -htmlcompress,\n                     -imagespng,\n                     -imagesjpg,\n                     -copy\"/>\n\n    <!--\n    *************************************************\n    * FUNCTION TARGETS                              *\n    *************************************************\n    -->\n\n    <target name=\"-clean\" description=\"(PRIVATE) Wipe the previous build (Deletes the dir.publish directory\">\n    <!-- This is a private target -->\n        <echo message=\"Cleaning up previous build directory...\"/>\n        <delete dir=\"./${dir.intermediate}/\"/>\n        <delete dir=\"./${dir.publish}/\"/>\n    </target>\n\n\n    <target name=\"-intro\" description=\"(PRIVATE) Kindly inform the developer about the impending magic\">\n    <!-- This is a private target -->\n\n        <echo message=\"=====================================================================\"/>\n        <echo message=\"Welcome to the HTML5 Boilerplate Build Script!\"/>\n        <echo message=\" \"/>\n        <echo message=\"We're going to get your site all ship-shape and ready for prime time.\"/>\n        <echo message=\" \"/>\n        <echo message=\"This should take somewhere between 15 seconds and a few minutes,\"/>\n        <echo message=\"mostly depending on how many images we're going to compress.\"/>\n        <echo message=\" \"/>\n        <echo message=\"Feel free to come back or stay here and follow along.\"/>\n        <echo message=\"=====================================================================\"/>\n        <echo message=\" \"/>\n        <echo message=\" \"/>\n\n    </target>\n\n    <target name=\"-mkdirs\" depends=\"-clean\">\n      <if>\n          <or>\n            <equals arg1=\"${dir.publish}\" arg2=\".\"/>\n            <equals arg1=\"${dir.publish}\" arg2=\"..\"/>\n            <equals arg1=\"${dir.publish}\" arg2=\"/\"/>\n            <equals arg1=\"${dir.publish}\" arg2=\"./\"/>\n            <equals arg1=\"${dir.publish}\" arg2=\"../\"/>\n          </or>\n          <then>\n            <fail message=\"Your dir.publish folder is set to ${dir.publish} which could delete your entire site or worse. Change it in project.properties\"/>\n          </then>\n          <else>\n            <echo message=\"Creating directory structure... ${dir.publish}\"/>\n\n            <mkdir dir=\"${dir.intermediate}\"/>\n            <copy todir=\"${dir.intermediate}\" includeEmptyDirs=\"true\">\n                <fileset dir=\"${dir.source}/\" excludes=\"${file.default.exclude}, ${file.exclude}\">\n                    <type type=\"dir\"/>\n                </fileset>\n            </copy>\n              <mkdir dir=\"${dir.publish}\"/>\n              <copy todir=\"${dir.publish}\" includeEmptyDirs=\"true\">\n                  <fileset dir=\"${dir.source}/\" excludes=\"${file.default.exclude}, ${file.exclude}\">\n                      <type type=\"dir\"/>\n                  </fileset>\n              </copy>\n          </else>\n      </if>\n    </target>\n\n    <target name=\"-copy\" depends=\"-mkdirs\">\n    <!-- This is a private target -->\n\n        <echo message=\"Copying over new files...\"/>\n\n        <copy todir=\"./${dir.publish}\">\n            <fileset dir=\"${dir.source}/\" excludes=\"${file.default.exclude}, ${file.exclude}\">\n                <!-- exclude files that are superseded by optimized versions with different names -->\n                <!-- this is not strictly necessary, but it avoids putting unreferenced files into your server -->\n                <exclude name=\"${dir.js}/**/*.js\"/>\n                <exclude name=\"${dir.css}/**/*.css\"/>\n                <exclude name=\"${file.manifest}\"/>\n            </fileset>\n        </copy>\n\n        <echo message=\"A copy of all non-dev files are now in: ./${dir.publish}.\"/>\n    </target>\n\n    <!-- JAVASCRIPT -->\n    <target name=\"-js.main.concat\" depends=\"-js.all.minify\" description=\"(PRIVATE) Concatenates the JS files in dir.js\">\n        <echo message=\"Concatenating Main JS scripts...\"/>\n        <!-- overwrite=no here means not to overwrite if the target is newer than the sources -->\n        <concat destfile=\"./${dir.intermediate}/${dir.js}/scripts-concat.js\" overwrite=\"no\">\n            <fileset dir=\"./${dir.intermediate}/\">\n                <include name=\"${dir.js.main}/plugins.js\"/>\n                <include name=\"${dir.js.main}/${file.root.script}\"/>\n            </fileset>\n        </concat>\n    </target>\n\n    <target name=\"-js.mylibs.concat\" depends=\"-js.all.minify\" description=\"(PRIVATE) Concatenates the JS files in dir.js.mylibs\">\n        <mkdir dir=\"./${dir.intermediate}/${dir.js.mylibs}\"/>\n\n        <echo message=\"Concatenating JS libraries\"/>\n        <!-- overwrite=no here means not to overwrite if the target is newer than the sources -->\n        <concat destfile=\"./${dir.intermediate}/${dir.js}/mylibs-concat.js\" overwrite=\"no\">\n            <fileset dir=\"./${dir.intermediate}/${dir.js.mylibs}/\"\n                includes=\"**/*.js\"\n                excludes=\"${file.js.bypass}\"/>\n\n        </concat>\n    </target>\n\n\n    <target name=\"-js.scripts.concat\" depends=\"-js.main.concat,-js.mylibs.concat\" if=\"build.concat.scripts\">\n        <echo message=\"Concatenating library file with main script file\"/>\n        <!-- overwrite=no here means not to overwrite if the target is newer than the sources -->\n        <concat destfile=\"./${dir.intermediate}/${dir.js}/scripts-concat.min.js\" overwrite=\"no\">\n            <fileset dir=\"./${dir.intermediate}/${dir.js}/\">\n                <include name=\"mylibs-concat.js\"/>\n                <include name=\"scripts-concat.js\"/>\n            </fileset>\n        </concat>\n\n        <checksum file=\"${dir.intermediate}/${dir.js}/scripts-concat.min.js\" algorithm=\"sha\" property=\"scripts.fullsha\" />\n        <propertyregex property=\"scripts.sha\" input=\"${scripts.fullsha}\" regexp=\".{${hash.length}}\" select=\"\\0\" />\n        <property name=\"scripts.js\" value=\"${dir.js}/${scripts.sha}.js\" />\n        <copy file=\"${dir.intermediate}/${dir.js}/scripts-concat.min.js\" tofile=\"${dir.publish}/${dir.js}/${scripts.sha}.js\" />\n    </target>\n\n\n    <target name=\"-js.all.minify\" depends=\"-mkdirs\" description=\"(PRIVATE) Minifies the scripts.js files created by js.scripts.concat\">\n        <echo message=\"Minifying scripts\"/>\n        <copy todir=\"${dir.intermediate}/\">\n            <fileset dir=\"${dir.source}/\" includes=\"${dir.js}/**/*.min.js\"  />\n        </copy>\n        <apply executable=\"java\" parallel=\"false\">\n            <fileset dir=\"${dir.source}/\" >\n                <include name=\"${dir.js}/**/*.js\"/>\n                <exclude name=\"${dir.js}/**/*.min.js\"/>\n            </fileset>\n            <arg line=\"-jar\"/>\n            <arg path=\"./${dir.build.tools}/closure-compiler-v1346.jar\"/>\n            <arg line=\"--js\"/>\n\t\t\t<srcfile/>\n\t\t\t<arg line=\"--compilation_level\" />\n\t\t\t <arg value=\"${scripts.compilation.level}\" />\n\t\t\t <arg line=\"--warning_level\" />\n\t\t\t <arg value=\"${scripts.compilation.warninglevel}\" />\n\t\t\t <arg line=\"--js_output_file\" />\n            <mapper type=\"glob\" from=\"*.js\" to=\"${basedir}/${dir.intermediate}/*.js\"/>\n            <targetfile/>\n        </apply>\n\n        <!-- at this point all js files are minified with their original names -->\n\n        <copy todir=\"${dir.publish}/\">\n          <fileset dir=\"${dir.intermediate}/\">\n              <include name=\"${dir.js}/**/*.js\"/>\n              <exclude name=\"${dir.js.mylibs}/**/*.js\"/>\n              <exclude name=\"${dir.js}/scripts-concat.js\"/>\n              <exclude name=\"${dir.js}/mylibs-concat.js\"/>\n              <exclude name=\"${dir.js}/scripts-concat.min.js\"/>\n              <exclude name=\"${dir.js}/plugins.js\"/>\n              <exclude name=\"${dir.js}/${file.root.script}\"/>\n          </fileset>\n        </copy>\n        <copy todir=\"${dir.publish}/${dir.js.mylibs}/\">\n            <fileset dir=\"${dir.source}/${dir.js.mylibs}/\"\n            includes=\"${file.js.bypass}\"/>\n        </copy>\n    </target>\n\n\n    <!-- HTML -->\n    <target name=\"-usemin\" depends=\"-js.scripts.concat,-css\" description=\"(PRIVATE) Replaces references to non-minified scripts\">\n        <echo message=\"Switching to minified js files...\"/>\n\n        <!-- Changes to style.css or scripts.js mean that the html must be updated, and it will be.\n             Unfortunately, the html we want to update may not have the tags we want to replace(because it was updated before).\n             This outofdate check ensures that the html files have the markers for us to replace. -->\n        <outofdate property=\"needhtmlrefresh\">\n            <sourcefiles>\n                <fileset dir=\"${dir.publish}\" includes=\"${style.css}, ${scripts.js}\"/>\n            </sourcefiles>\n            <targetfiles>\n                <fileset dir=\"${dir.intermediate}\" includes=\"${page-files}\"/>\n            </targetfiles>\n        </outofdate>\n\n        <!-- force the files to be overwritten with older copies from source if needhtmlrefresh is set -->\n        <copy todir=\"${dir.intermediate}\" overwrite=\"${needhtmlrefresh}\">\n            <fileset dir=\"${dir.source}\" includes=\"${page-files}\"/>\n        </copy>\n\n        <!-- switch from a regular jquery to minified -->\n        <replaceregexp match=\"jquery-(\\d|\\d(\\.\\d)+)\\.js\" replace=\"jquery-\\1.min.js\" flags=\"g\">\n            <fileset dir=\"./${dir.intermediate}\" includes=\"${page-files}\"/>\n        </replaceregexp>\n        <!-- switch any google CDN reference to minified -->\n        <replaceregexp match=\"(\\d|\\d(\\.\\d)+)\\/jquery\\.js\" replace=\"\\1/jquery.min.js\" flags=\"g\">\n            <fileset dir=\"./${dir.intermediate}\" includes=\"${page-files}\"/>\n        </replaceregexp>\n\n        <echo>Kill off those versioning flags: ?v=2</echo>\n        <replaceregexp match='\\?v=\\d+\">' replace='\">' flags=\"g\">\n            <fileset dir=\"./${dir.intermediate}\" includes=\"${page-files}\"/>\n        </replaceregexp>\n\n        <echo>Remove favicon.ico reference if it is pointing to the root</echo>\n        <replaceregexp match=\"&lt;link rel=[&quot;']shortcut icon[&quot;'] href=[&quot;']/favicon\\.ico[&quot;']&gt;\" replace=\"\">\n            <fileset dir=\"${dir.intermediate}\" includes=\"${page-files}\"/>\n        </replaceregexp>\n        <!-- we maintain the apple-touch-icon reference for Android 2.2   www.ravelrumba.com/blog/android-apple-touch-icon\n        <replace token=\"&lt;link rel=&quot;apple-touch-icon&quot; href=&quot;/apple-touch-icon.png&quot;>\" value=\"\">\n            <fileset dir=\"${dir.intermediate}\" includes=\"${page-files}\"/>\n        </replace>\n        -->\n\n        <echo message=\"Update the HTML to reference our concatenated script file: ${scripts.js}\"/>\n        <!-- style.css replacement handled as a replacetoken above -->\n        <replaceregexp match=\"&lt;!-- scripts concatenated [\\d\\w\\s\\W]*&lt;script.*src=['&quot;]?(.*)/${file.root.script}(?:\\?.*)?['&quot;]?\\s*&gt;\\s*&lt;/script&gt;[\\d\\w\\s\\W]*&lt;!-- end ((scripts)|(concatenated and minified scripts))\\s*--&gt;\"\n        \treplace=\"&lt;script defer src='\\1/${scripts.sha}.js\\'&gt;&lt;/script&gt;\" flags=\"m\">\n            <fileset dir=\"${dir.intermediate}\" includes=\"${page-files}\"/>\n        </replaceregexp>\n        <!--[! use comments like this one to avoid having them get minified -->\n\n        <echo message=\"Updating the HTML with the new css filename: ${style.css}\"/>\n\n        <replaceregexp match=\"&lt;link rel=['&quot;]?stylesheet['&quot;]?\\s+href=['&quot;]?(.*)/${file.root.stylesheet}(?:\\?.*)?['&quot;]?\\s*&gt;\"\n        \treplace=\"&lt;link rel='stylesheet' href='\\1/${css.sha}.css'&gt;\" flags=\"m\">\n            <fileset dir=\"${dir.intermediate}\" includes=\"${page-files}\"/>\n        </replaceregexp>\n\n    </target>\n\n\n    <target name=\"-manifest\" depends=\"-usemin\">\n        <if>\n            <isset property=\"file.manifest\" />\n            <then>\n                <echo message=\"copying a fresh ${dir.build}/config/${file.manifest} to /${dir.intermediate}\"/>\n\n                <delete file=\"${dir.intermediate}/${file.manifest}\"/>\n                <copy file=\"${dir.build}/config/${file.manifest}\" tofile=\"${dir.intermediate}/${file.manifest}\" />\n\n                <echo message=\"manifest creation\" />\n\n                <!-- update version -->\n                <echo message=\"Updating the site.manifest version date to today, current time\"/>\n                <tstamp>\n                    <format property=\"TODAY\" pattern=\"yyyy-MM-dd HH:mm:ss\"/>\n                </tstamp>\n                <replaceregexp match=\"# version .+\" replace=\"# version ${TODAY}\" file=\"${dir.intermediate}/${file.manifest}\"/>\n\n                <!-- add html files -->\n                <echo message=\"Updating the site.manifest with html files: ${page-files}\"/>\n                <for list=\"${page-files}\" param=\"file\" delimiter=\",\" trim=\"true\">\n                    <sequential>\n                        <replaceregexp match=\"# html files\" replace=\"# html files${line.separator}@{file}\" file=\"${dir.intermediate}/${file.manifest}\" />\n                    </sequential>\n                </for>\n\n                <!-- add stylesheet files -->\n                <echo message=\"Updating the site.manifest with the new css filename: ${style.css}\"/>\n                <replace token=\"# css files\" value=\"# css files${line.separator}${style.css}\" file=\"${dir.intermediate}/${file.manifest}\" />\n\n                <!-- add javascript files -->\n                <echo message=\"Updating the site.manifest with the new js filename: ${scripts.js}\"/>\n                <for param=\"file\">\n                    <path>\n                        <fileset dir=\"./${dir.intermediate}/${dir.js.mylibs}/\"\n                            includes=\"${file.js.bypass}\" />\n                    </path>\n                    <sequential>\n                        <basename property=\"filename.@{file}\" file=\"@{file}\" />\n                        <replaceregexp match=\"# js files\" replace=\"# js files${line.separator}${dir.js.mylibs}/${filename.@{file}}\" file=\"${dir.intermediate}/${file.manifest}\" />\n                    </sequential>\n                </for>\n                <for param=\"file\">\n                    <path>\n                        <fileset dir=\"./${dir.intermediate}/${dir.js.libs}/\"\n                            includes=\"*.min.js\"/>\n                    </path>\n                    <sequential>\n                        <basename property=\"filename.@{file}\" file=\"@{file}\" />\n                        <replaceregexp match=\"# js files\" replace=\"# js files${line.separator}${dir.js.libs}/${filename.@{file}}\" file=\"${dir.intermediate}/${file.manifest}\" />\n                    </sequential>\n                </for>\n                <replace token=\"# js files\" value=\"# js files${line.separator}${scripts.js}\" file=\"${dir.intermediate}/${file.manifest}\" />\n\n                <!-- add image files -->\n                <echo message=\"Updating the site.manifest with the images\"/>\n                <for param=\"file\">\n                    <path>\n                        <fileset dir=\"./${dir.source}/${dir.images}/\" includes=\"**/*\"/>\n                    </path>\n                    <sequential>\n                        <basename property=\"filename.@{file}\" file=\"@{file}\" />\n                        <replaceregexp match=\"# image files\" replace=\"# image files${line.separator}${dir.images}/${filename.@{file}}\" file=\"${dir.intermediate}/${file.manifest}\" />\n                    </sequential>\n                </for>\n\n                <echo message=\"copying ${file.manifest} to /${dir.publish}\"/>\n                <copy file=\"${dir.intermediate}/${file.manifest}\" tofile=\"${dir.publish}/${file.manifest}\" />\n\n                <echo>Add manifest attribute to HTML: </echo>\n                <replaceregexp match=\"&lt;html (.*?)>\\s*?&lt;!--&lt;!\\[endif\" replace='&lt;html \\1 manifest=\"${file.manifest}\"> &lt;!--&lt;![endif' flags=\"g\">\n                    <fileset dir=\"./${dir.intermediate}\" includes=\"${page-files}\"/>\n                </replaceregexp>\n\n            </then>\n            <else>\n                <echo message=\"no manifest.appcache generated!\" />\n            </else>\n        </if>\n    </target>\n\n    <target name=\"-htmlclean\" depends=\"-usemin\">\n        <echo message=\"Run htmlcompressor on the HTML\"/>\n        <echo message=\" - maintaining whitespace\"/>\n        <echo message=\" - removing html comments\"/>\n        <echo message=\" - compressing inline style/script tag contents\"/>\n        <apply executable=\"java\" parallel=\"false\" dest=\"./${dir.publish}/\" >\n            <fileset dir=\"./${dir.intermediate}/\" includes=\"${page-files}\"/>\n            <arg value=\"-jar\"/>\n            <arg path=\"./${dir.build.tools}/${tool.htmlcompressor}\"/>\n            <arg line=\"--preserve-multi-spaces\"/>\n            <arg line=\"--remove-quotes\"/>\n            <arg line=\"--compress-js\"/>\n            <arg line=\"--compress-css\"/>\n            <arg line=\"--preserve-php\"/>\n            <arg line=\"--preserve-ssi\"/>\n            <srcfile/>\n            <arg value=\"-o\"/>\n            <mapper type=\"glob\" from=\"*\" to=\"../${dir.publish}/*\"/>\n            <targetfile/>\n        </apply>\n    </target>\n\n\n    <target name=\"-htmlbuildkit\" depends=\"-usemin\">\n        <echo message=\"Run htmlcompressor on the HTML\"/>\n        <echo message=\" - maintaining whitespace\"/>\n        <echo message=\" - retain html comments\"/>\n        <echo message=\" - compressing inline style/script tag contents\"/>\n        <apply executable=\"java\" parallel=\"false\" dest=\"./${dir.publish}/\" >\n            <fileset dir=\"./${dir.intermediate}/\" includes=\"${page-files}\"/>\n            <arg value=\"-jar\"/>\n            <arg path=\"./${dir.build.tools}/${tool.htmlcompressor}\"/>\n            <arg value=\"--preserve-comments\"/>\n            <arg line=\"--preserve-multi-spaces\"/>\n            <arg line=\"--compress-js\"/>\n            <arg line=\"--compress-css\"/>\n            <arg line=\"--preserve-php\"/>\n            <arg line=\"--preserve-ssi\"/>\n            <srcfile/>\n            <arg value=\"-o\"/>\n            <mapper type=\"glob\" from=\"*\" to=\"../${dir.publish}/*\"/>\n            <targetfile/>\n        </apply>\n    </target>\n\n\n    <target name=\"-htmlcompress\" depends=\"-usemin\">\n        <echo message=\"Run htmlcompressor on the HTML\"/>\n        <echo message=\" - removing unnecessary whitespace\"/>\n        <echo message=\" - removing html comments\"/>\n        <echo message=\" - compressing inline style/script tag contents\"/>\n        <apply executable=\"java\" parallel=\"false\" dest=\"./${dir.publish}/\" >\n            <fileset dir=\"./${dir.intermediate}/\" includes=\"${page-files}\"/>\n            <arg value=\"-jar\"/>\n            <arg path=\"./${dir.build.tools}/${tool.htmlcompressor}\"/>\n            <arg line=\"--remove-quotes\"/>\n            <arg line=\"--compress-js\"/>\n            <arg line=\"--compress-css\"/>\n            <arg line=\"--preserve-php\"/>\n            <arg line=\"--preserve-ssi\"/>\n            <srcfile/>\n            <arg value=\"-o\"/>\n            <mapper type=\"glob\" from=\"*\" to=\"../${dir.publish}/*\"/>\n            <targetfile/>\n        </apply>\n    </target>\n\n\n    <!-- CSS -->\n\n    <target name=\"-css-remove-concatenated-stylesheets\">\n            <echo>Removing ${css_file} from html</echo>\n            <replaceregexp match=\"&lt;link.+href=&quot;.*${css_file}&quot;.*&gt;\" replace=\"  \">\n                <fileset dir=\"${dir.intermediate}\" includes=\"${page-files}\"/>\n            </replaceregexp>\n    </target>\n\n\n    <target name=\"css-split\" description=\"turns style.css into multiple files @imported together\">\n        <copy file=\"${dir.source}/${dir.css}/${file.root.stylesheet}\" tofile=\"${dir.source}/${dir.css}/${file.root.stylesheet}.temp\"/>\n\n        <replaceregexp file=\"${dir.source}/${dir.css}/${file.root.stylesheet}.temp\"\n               match=\".*\"\n               replace=\"/* remove me */\" flags=\"s\" />\n\n        <loadfile property=\"root\" srcfile=\"${dir.source}/${dir.css}/${file.root.stylesheet}\"/>\n        <var name=\"curr.buffer\" value=\"\"/>\n\n        <for delimiter=\"${line.separator}\" param=\"currline\" list=\"${root}\">\n            <sequential>\n                <!-- does this line contain an h5bp-import? -->\n                <propertyregex property=\"export.name\" input=\"@{currline}\" regexp=\"^.*==\\|== +(.*) +==+$\" select=\"\\1\" casesensitive=\"true\" override=\"true\" />\n                <if>\n                    <isset property=\"export.name\"/>\n                    <then>\n                        <propertyregex property=\"export.name\" input=\"${export.name}\" regexp=\" \" replace=\".\" global=\"true\" override=\"true\" />\n                        <var name=\"export.name\" value=\"${export.name}.css\"/>\n\n                        <if>\n                            <isset property=\"curr.file\"/>\n                            <then>\n                                <!-- create curr.file -->\n                                <copy file=\"${dir.source}/${dir.css}/${file.root.stylesheet}\" tofile=\"${dir.source}/${dir.css}/${curr.file}\" overwrite=\"true\"/>\n                                <!-- write the curr.buffer into the curr.file -->\n                                <replaceregexp file=\"${dir.source}/${dir.css}/${curr.file}\"\n                                       match=\".*\"\n                                       replace=\"${curr.buffer}\" flags=\"s\" />\n\n                                <var name=\"curr.buffer\" value=\"\"/>\n                                <var name=\"curr.file\" unset=\"true\"/>\n                            </then>\n                        </if>\n                        <var name=\"curr.file\" value=\"${export.name}\"/>\n                        <var name=\"export.name\" unset=\"true\"/>\n\n                        <!-- insert import line into new root -->\n                        <replace file=\"${dir.source}/${dir.css}/${file.root.stylesheet}.temp\" token=\"/* remove me */\" value=\"@import url(${curr.file});${line.separator}/* remove me */\"/>\n                    </then>\n                </if>\n                <var name=\"curr.buffer\" value=\"${curr.buffer}@{currline}${line.separator}\" />\n            </sequential>\n        </for>\n        <!-- one more time to write out the last file -->\n        <if>\n            <isset property=\"curr.file\"/>\n            <then>\n                <!-- create curr.file -->\n                <copy file=\"${dir.source}/${dir.css}/${file.root.stylesheet}\" tofile=\"${dir.source}/${dir.css}/${curr.file}\" overwrite=\"true\"/>\n                <!-- write the curr.buffer into the curr.file -->\n                <replaceregexp file=\"${dir.source}/${dir.css}/${curr.file}\"\n                       match=\".*\"\n                       replace=\"${curr.buffer}\" flags=\"s\" />\n\n                <var name=\"curr.buffer\" value=\"\"/>\n                <var name=\"curr.file\" unset=\"true\"/>\n            </then>\n        </if>\n        <replace file=\"${dir.source}/${dir.css}/${file.root.stylesheet}.temp\" token=\"/* remove me */\" value=\"${curr.buffer}\"/>\n        <copy file=\"${dir.source}/${dir.css}/${file.root.stylesheet}\" tofile=\"${dir.source}/${dir.css}/${file.root.stylesheet}.orig\" overwrite=\"false\"/>\n        <move file=\"${dir.source}/${dir.css}/${file.root.stylesheet}.temp\" tofile=\"${dir.source}/${dir.css}/${file.root.stylesheet}\" overwrite=\"false\"/>\n    </target>\n\n    <target name=\"-css\" depends=\"-mkdirs\" description=\"Concatenates and Minifies any stylesheets @imported via the file.stylesheets\">\n        <echo message=\"Concatenating any @imports...\"/>\n\n        <!-- copy source file to intermediate directory -->\n        <copy file=\"${dir.source}/${dir.css}/${file.root.stylesheet}\" tofile=\"${dir.intermediate}/${dir.css}/${file.root.stylesheet}\"/>\n\n        <!-- replace imports with h5bp-import tags (part 1) this one wraps @media types -->\n        <replaceregexp file=\"${dir.intermediate}/${dir.css}/${file.root.stylesheet}\"\n                        match=\"^@import\\s+(?:url\\s*\\(\\s*['&quot;]?|['&quot;])((?!http:|https:|ftp:|\\/\\/)[^&quot;^'^\\s]+)(?:['&quot;]?\\s*\\)|['&quot;])\\s*([\\w\\s\\(\\)\\d\\:,\\-]*);.*$\"\n                       replace=\"@media \\2{ /* h5bp-import: \\1 */ }\" byline=\"true\" />\n\n        <!-- replace imports with h5bp-import tags (part 2) -->\n        <replaceregexp file=\"${dir.intermediate}/${dir.css}/${file.root.stylesheet}\"\n                       match=\"^@media \\{ (/\\* .* \\*/) \\}\" replace=\"\\1\" byline=\"true\" />\n\n        <!-- copy skeleton to concat file -->\n        <copy file=\"${dir.intermediate}/${dir.css}/${file.root.stylesheet}\"\n              tofile=\"${dir.intermediate}/${dir.css}/style-concat.css\" overwrite=\"true\"/>\n\n        <!-- load the file into a property -->\n        <loadfile property=\"imports\" srcfile=\"${dir.intermediate}/${dir.css}/${file.root.stylesheet}\"/>\n\n        <var name=\"concat-files\" value=\"${file.root.stylesheet}\"/>\n\n        <!-- go over the file line by line -->\n        <for delimiter=\"${line.separator}\" param=\"import\" list=\"${imports}\">\n            <sequential>\n                <!-- does this line contain an h5bp-import? -->\n                <propertyregex property=\"file.name\" input=\"@{import}\" regexp=\"/\\* h5bp-import: (.*) \\*/\" select=\"\\1\" casesensitive=\"true\" override=\"true\" />\n\n                <if>\n                    <isset property=\"file.name\"/>\n                    <then>\n                        <var name=\"concat-files\" value=\"${file.name},${concat-files}\"/>\n\n                        <!-- load the file into a variable -->\n                        <loadfile property=\"file.contents\" srcFile=\"${dir.source}/${dir.css}/${file.name}\"/>\n\n                        <!-- pop that file into the concatenated output file -->\n                        <replace file=\"${dir.intermediate}/${dir.css}/style-concat.css\" token=\"/* h5bp-import: ${file.name} */\" value=\"${file.contents}\"/>\n\n                        <var name=\"file.contents\" unset=\"true\"/>\n                    </then>\n                </if>\n            </sequential>\n        </for>\n        <echo message=\"Minifying css...\"/>\n\n        <apply executable=\"java\" parallel=\"false\">\n            <fileset dir=\"${dir.intermediate}/${dir.css}/\" includes=\"style-concat.css\"/>\n            <arg line=\"-jar\"/>\n            <arg path=\"${dir.build.tools}/${tool.yuicompressor}\"/>\n            <srcfile/>\n            <arg line=\"-o\"/>\n            <mapper type=\"merge\" to=\"${basedir}/${dir.intermediate}/${dir.css}/style-concat.min.css\"/>\n            <targetfile/>\n        </apply>\n\n        <checksum file=\"${dir.intermediate}/${dir.css}/style-concat.min.css\" algorithm=\"sha\" property=\"css.fullsha\" />\n        <propertyregex property=\"css.sha\" input=\"${css.fullsha}\" regexp=\".{${hash.length}}\" select=\"\\0\" />\n        <property name=\"style.css\" value=\"${dir.css}/${css.sha}.css\" />\n        <copy file=\"${dir.intermediate}/${dir.css}/style-concat.min.css\" tofile=\"${dir.publish}/${dir.css}/${css.sha}.css\" />\n\n        <echo message=\"Minifying any unconcatenated css files...\"/>\n\n        <apply executable=\"java\" parallel=\"false\">\n            <fileset dir=\"${dir.source}/${dir.css}/\" excludes=\"${concat-files}\" includes=\"**/*.css\"/>\n            <arg line=\"-jar\"/>\n            <arg path=\"${dir.build.tools}/${tool.yuicompressor}\"/>\n            <srcfile/>\n            <arg line=\"-o\"/>\n            <mapper type=\"glob\" from=\"*.css\" to=\"${basedir}/${dir.publish}/${dir.css}/*.css\"/>\n            <targetfile/>\n        </apply>\n        <foreach list=\"${file.stylesheets}\" param=\"css_file\" target=\"-css-remove-concatenated-stylesheets\" />\n    </target>\n\n\n    <!-- IMAGES -->\n    <target name=\"-imagespng\" depends=\"-mkdirs\" description=\"(PRIVATE) Optimizes .png images using optipng\">\n        <echo message=\"Optimizing images...\"/>\n        <echo message=\"This part might take a while. But everything else is already done.\"/>\n        <echo message=\" \"/>\n\n\n        <echo message=\"First, we run optipng on the .png files...\"/>\n\n        <!-- osfamily=unix is actually true on OS X as well -->\n        <!-- On *nix's and OS X, check for optipng and give a helpful message if it's not installed -->\n        <if>\n            <and>\n                <os family=\"unix\" />\n                <available file=\"optipng\" filepath=\"${ENV.PATH}\" />\n            </and>\n            <then>\n                <!-- work around https://sourceforge.net/tracker/?func=detail&aid=2671422&group_id=151404&atid=780916 -->\n                <delete>\n                    <fileset dir=\"./${dir.publish}/${dir.images}/\">\n                        <include name=\"**/*.png\"/>\n                    </fileset>\n                </delete>\n                <apply executable=\"optipng\" dest=\"./${dir.publish}/${dir.images}/\" osfamily=\"unix\">\n                    <fileset dir=\"./${dir.source}/${dir.images}/\" includes=\"**/*.png\"  excludes=\"${images.bypass}, ${images.default.bypass}\"/>\n                    <arg value=\"-quiet\"/>\n                    <arg value=\"-o7\"/>\n                    <arg value=\"-out\"/>\n                    <targetfile/>\n                    <srcfile/>\n                    <mapper type=\"identity\"/>\n                </apply>\n            </then>\n            <elseif>\n                <os family=\"unix\" />\n                <then>\n                    <echo message=\"*** optipng NOT INSTALLED. SKIPPING OPTIMIZATION OF PNGs.\" />\n                    <echo message=\"*** Install optipng to enable png optimization.\" />\n                    <echo message=\"*** For instructions see 'Dependencies' at: http://html5boilerplate.com/docs/#Build-script#dependencies\" />\n                </then>\n            </elseif>\n            <elseif>\n                <os family=\"windows\" />\n                <!-- work around https://sourceforge.net/tracker/?func=detail&aid=2671422&group_id=151404&atid=780916 -->\n                <then>\n                    <delete>\n                        <fileset dir=\"./${dir.publish}/${dir.images}/\">\n                            <include name=\"**/*.png\"/>\n                        </fileset>\n                    </delete>\n                    <apply executable=\"${basedir}/${dir.build.tools}/optipng-0.6.4-exe/optipng.exe\" dest=\"./${dir.publish}/${dir.images}/\" osfamily=\"windows\">\n                        <fileset dir=\"./${dir.source}/${dir.images}/\" includes=\"**/*.png\"  excludes=\"${images.bypass}, ${images.default.bypass}\"/>\n                        <arg value=\"-quiet\"/>\n                        <arg value=\"-o7\"/>\n                        <arg value=\"-out\"/>\n                        <targetfile/>\n                        <srcfile/>\n                        <mapper type=\"identity\"/>\n                    </apply>\n                </then>\n            </elseif>\n        </if>\n    </target>\n\n\n    <target name=\"-imagesjpg\" depends=\"-mkdirs\" description=\"(PRIVATE) Optimizes .jpg images using jpegtan\">\n        <echo message=\"Now, we clean up those jpgs...\"/>\n\n        <if>\n            <equals arg1=\"${images.strip.metadata}\" arg2=\"true\"/>\n            <then>\n                <var name=\"strip-meta-tags\" value=\"none\"/>\n            </then>\n            <else>\n                <var name=\"strip-meta-tags\" value=\"all\"/>\n            </else>\n        </if>\n\n        <!-- On *nix's and OS X, check for jpegtran and give a helpful message if it's not installed -->\n        <if>\n            <and>\n                <os family=\"unix\" />\n                <available file=\"jpegtran\" filepath=\"${ENV.PATH}\" />\n            </and>\n            <then>\n                <apply executable=\"jpegtran\" dest=\"./${dir.publish}/${dir.images}\" osfamily=\"unix\">\n                    <fileset dir=\"${dir.source}/${dir.images}\" includes=\"**/*.jpg\" excludes=\"${images.bypass}, ${images.default.bypass}\"/>\n                    <arg value=\"-copy\"/>\n                    <arg value=\"${strip-meta-tags}\"/>\n                    <arg value=\"-optimize\"/>\n                    <arg value=\"-outfile\"/>\n                    <targetfile/>\n                    <srcfile/>\n                    <mapper type=\"identity\"/>\n                    <!-- you may want to flag optimized images. If so, do it here. Otherwise change this to type=\"identity\" -->\n                    <!--<mapper type=\"glob\" from=\"*.jpg\" to=\"*.jpg\"/>-->\n                </apply>\n            </then>\n            <elseif>\n                <os family=\"unix\" />\n                <then>\n                    <echo message=\"*** jpegtran NOT INSTALLED. SKIPPING OPTIMIZATION OF JPEGs.\" />\n                    <echo message=\"*** Install jpegtran to enable jpeg optimization.\" />\n                    <echo message=\"*** For instructions see 'Dependencies' at: http://html5boilerplate.com/docs/#Build-script#dependencies\" />\n                </then>\n            </elseif>\n        </if>\n\n        <apply executable=\"${basedir}/${dir.build.tools}/jpegtran.exe\" dest=\"./${dir.publish}/${dir.images}\" osfamily=\"windows\">\n            <fileset dir=\"${dir.source}/${dir.images}\" includes=\"**/*.jpg\"  excludes=\"${images.bypass}, ${images.default.bypass}\"/>\n            <arg value=\"-copy\"/>\n            <arg value=\"${strip-meta-tags}\"/>\n            <arg value=\"-optimize\"/>\n            <arg value=\"-outfile\"/>\n            <targetfile/>\n            <srcfile/>\n            <mapper type=\"identity\"/>\n            <!-- you may want to flag optimized images. If so, do it here. Otherwise change this to type=\"identity\" -->\n            <!--<mapper type=\"glob\" from=\"*.jpg\" to=\"*.jpg\"/>-->\n        </apply>\n    </target>\n\n\n    <target name=\"-imgcopy\" depends=\"-mkdirs\">\n        <echo message=\"Copying over the unmodified images.\"/>\n\n        <copy todir=\"./${dir.publish}/${dir.images}\">\n            <fileset dir=\"${dir.source}/${dir.images}\"  includes=\"**/*.jpg, **/*.png\"/>\n        </copy>\n    </target>\n\n\t<!-- Import project.xml (put any custom build targets in this file so that they aren't overwritten when build.xml is updated) -->\n\t<!-- See: https://github.com/h5bp/html5-boilerplate/issues/704 -->\n\t<import file=\"./project.xml\" />\n\n</project>"
  },
  {
    "path": "build/config/default.properties",
    "content": "#\n# Default Build Settings\n# you can override these settings on a project basis in a project.properties file\n# so probably best not to touch these as they could be overwritten in later versions!\n#\n\n\n#\n# Directory Paths\n#\ndir.source          = .\ndir.intermediate    = intermediate\ndir.publish         = publish\ndir.build           = build\ndir.build.tools     = ${dir.build}/tools\ndir.test            = test\ndir.demo            = demo\ndir.js              = js\ndir.js.main         = ${dir.js}\n# scripts in the lib directory will only be minified, not concatenated together\ndir.js.libs         = ${dir.js}/libs\ndir.js.mylibs       = ${dir.js}/mylibs\ndir.css             = css\ndir.images          = img\n\n\n#\n# HTML, PHP, etc files to clean and update script/css references\n#\nfile.pages.default.include  = index.html, 404.html\n\n# You will need to include the property file.pages.include in your project.properties file\n# and add any extra pages you want to be updated by the scripts in a comma separated list\n\n\n# the server configuration you're going with. If you don't use apache,\n#   get a different one here: github.com/h5bp/server-configs \n\nfile.serverconfig           = .htaccess\n\n#\n# Files not to be copied over by the script to the publish directory\n#\nfile.default.exclude        = .gitignore, .project, .settings, README.markdown, README.md, **/.git/**, **/.svn/**, ${dir.test}/**, ${dir.demo}/**, ${dir.intermediate}/**, ${dir.publish}/**, ${dir.build}/**, **/nbproject/**, *.komodoproject, **/.komodotools/**, **/dwsync.xml, **_notes, **/.hg/**, **/.idea/**\n# Declare the file.exclude property in your project.properties file if you want to exclude files / folders you have added\n# Note: you cannot declare an empty file.exclude property\n\n#\n# Bypass Optimization for these files\n#\n# file.default.js.bypass\n# If set, these files will not be optimized (minifications, concatinations, image optimizations will not be applied)\n# Note: you cannot declare an empty file.default.bypass property\n\n#\n# Root Script file\n# this is the file that will be swapped for the concatenated and minified javascript.\n#\nfile.root.script    = script.js\n\n#\n# Root Stylesheet\n# this is the file that contains the @import directives\n#\nfile.root.stylesheet    = style.css\n\n#\n# Default Stylesheet\n#\nfile.default.stylesheets    =\n\n#\n# Script Optimisation\n#\n# If set, concat libraries with main scripts file, producing single script file\nbuild.concat.scripts        = true\n\n# default options for closure compiler.\nscripts.compilation.level =SIMPLE_OPTIMIZATIONS\nscripts.compilation.warninglevel = QUIET\n\n#\n# Image Optimisation\n#\nimages.strip.metadata       = true\n# Seting this to true will strip the metadata from all jpeg files.\n# YOU SHOULD ONLY DO THIS IF YOU OWN THE COPYRIGHT TO ALL THE IMAGES IN THE BUILD\n\n#\n# Bypass Optimization for these image files or folders\n#\n# images.default.bypass\n# If set, these images will not be optimized\n# Note: you cannot declare an empty images.default.bypass property\n\n\n# Build Info\nbuild.version.info          = buildinfo.properties\nbuild.scripts.dir           = ${dir.build}/build-scripts\n\n# Tools\ntool.yuicompressor          = yuicompressor-2.4.5.jar\ntool.htmlcompressor         = htmlcompressor-1.4.3.jar\ntool.csscompressor          = css-compressor/cli.php\ntool.rhino                  = rhino.jar\ntool.jslint                 = fulljslint.js\ntool.jshint                 = fulljshint.js\ntool.csslint                = csslint-rhino.js\n\n# Default Lint Utils Options\ntool.jshint.opts            = maxerr=25,eqeqeq=true\ntool.jslint.opts            = maxerr=25,evil=true,browser=true,eqeqeq=true,immed=true,newcap=true,nomen=true,es5=true,rhino=true,undef=true,white=false,devel=true\ntool.csslint.opts           =\n\n# Default hash length\nhash.length                 = 7\n"
  },
  {
    "path": "build/config/manifest.appcache",
    "content": "CACHE MANIFEST\n\n# version xxxxxxxxx\n\nCACHE:\n# html files\n\n\n# css files\n\n\n\n# js files\n\n\n\n# image files\n\nFALLBACK:\n\nNETWORK:\n*"
  },
  {
    "path": "build/config/project.properties",
    "content": "# project.properties file defines overrides for default.properties\n\n# Explanation: This file should be created by each user as and when he or she needs to override particular values.\n# Consequently, it should not be placed under version control.\n\n\n# Stylesheets\n#\n# Note: Stylesheets will be concatenated in the order they are listed in the file.stylesheets property (i.e. the last\n# file listed will be at the end of the concatenated file), so it probably makes sense to have the main style.css file\n# as the first entry\n# Example:\n# file.stylesheets  = style.css, lightbox.css, plugin.css\n#\nfile.stylesheets  =\n\n\n# Web Pages\n#\n# These are the pages (files) that will be served to users (.html, .php, .asp, etc). Files in this property will\n# be minified / optimised and have any stylesheet or javascript references updated to the minified examples\n#\n# The paths need to be relative\n#\n# Files can be added in a comma separated form\nfile.pages        =\n\n\n# site manifest for offline\n# this is the name of the manifest file you declared in the <html> tag\n# Uncomment this line to enable appcache generation:\n# file.manifest    = manifest.appcache\n\n# Excluded files and dirs\n#\n# Add any files or directories you add to the project and do not want to be copied to the publish directory as a\n# comma separated list\n# These files are ignored in addition to the default ones specified in default.properties.\nfile.exclude      =\n\n# Bypassed JavaScript files and dirs\n#\n# Add any files or folders within the mylibs directory that you want to be copied to the publish directory as a\n# comma separated list\n# These files will not be concatenated or minimized and will simply be copied over as is.\n# Note: you cannot declare an empty file.bypass property, it would exclude the entire mylibs folder\n# Example:\n# file.js.bypass = widgets.js, gadgets.js, gidgets.js\n# file.js.bypass =\n\n# Clousre Compiler Options\n#\n# options are WHITESPACE_ONLY, SIMPLE_OPTIMIZATIONS, ADVANCED_OPTIMIZATIONS\n# scripts.compilation.level =  SIMPLE_OPTIMIZATIONS\n# options are QUIET DEFAULT AND VERBOSE\n# scripts.compilation.warninglevel = QUIET\n\n#\n# Specify an environment to build\n#\n# By Default, it builds a production environment\n# Set to dev if building a development environment\n# Set to test if building a test environment\nenv               =\n\n#\n# Bypass Optimization for these image files or folders\n#\n# images.bypass\n# If set, these images will not be optimized\n# Note: you cannot declare an empty images.bypass property, it would exclude the entire img folder from being optimized\n\n# Directory Structure\n#\n# Override any directory paths specific to this project\n#\n# dir.publish\n# dir.js\n# dir.js.libs\n# dir.js.mylibs\n# dir.css\n# dir.images\n\n# Override default JSHint Options (see http://jshint.com/ for description of options)\n#tool.jshint.opts =\n\n# Override default JSLint Options (see http://www.jslint.com/lint.html for description of options)\n#tool.jslint.opts =\n\n# Override default CSSLint Options (see http://csslint.net/about.html#settings for description of options)\n#tool.csslint.opts =\n\n# set the hash length used for versioning css and js files.\n# valid values are between 1 and 40.\n# shorter values use less bytes at the expense of increasing the probability of a hash collision.\n#hash.length = 7\n"
  },
  {
    "path": "build/createproject.sh",
    "content": "#!/usr/bin/env bash\n\n#Generate a new project from your HTML5 Boilerplate repo clone\n#by: Rick Waldron & Michael Cetrulo\n\n\n##first run\n# $ cd  html5-boilerplate/build\n# $ chmod +x createproject.sh && ./createproject.sh [new_project]\n\n##usage\n# $ cd  html5-boilerplate/build\n# $ ./createproject.sh [new_project]\n\n#\n# If [new_project] is not specified the user we will prompted to enter it.\n#\n# The format of [new_project] should ideally be lowercase letters with no\n# spaces as it represents the directory name that your new project will live\n# in.\n#\n# If the new project is specified as just a name ( \"foo\" ) then the path\n# will be a sibling to html5-boilerplate's directory.\n#\n# If the new project is specified with an absolute path ( \"/home/user/foo\" )\n# that path will be used.\n#\n\n# find project root (also ensure script is ran from within repo)\nsrc=$(git rev-parse --show-toplevel) || {\n  echo \"try running the script from within html5-boilerplate directories.\" >&2\n  exit 1\n}\n[[ -d $src ]] || {\n  echo \"fatal: could not determine html5-boilerplate's root directory.\" >&2\n  echo \"try updating git.\" >&2\n  exit 1\n}\n\nif [ $# -eq 1 ]\nthen\n    # get a name for new project from command line arguments\n    name=\"$1\"\nfi\n\n# get a name for new project from input\nwhile [[ -z $name ]]\ndo\n    echo \"To create a new html5-boilerplate project, enter a new directory name:\"\n    read name || exit\ndone\n\nif [[ \"$name\" = /* ]]\nthen\n    dst=$name\nelse\n    dst=$src/../$name\nfi\n\nif [[ -d $dst ]]\nthen\n    echo \"$dst exists\"\nelse\n    #create new project\n    mkdir -p -- \"$dst\" || exit 1\n\n    #success message\n    echo \"Created Directory: $dst\"\n\n    cd -- \"$src\"\n    cp -vr -- css js img build test *.html *.xml *.txt *.png *.ico .htaccess \"$dst\"\n\n    #success message\n    echo \"Created Project: $dst\"\nfi\n\n"
  },
  {
    "path": "build/project.xml",
    "content": "<?xml version=\"1.0\"?>\n<!DOCTYPE project>\n<project name=\"Project Build\" default=\"build\" basedir=\"../\">\n\t\n    <!-- Use this file to define any custom build targets (for example, automatically deploying via FTP). -->\n\n</project>"
  },
  {
    "path": "build/runbuildscript.bat",
    "content": "REM # This is for windows users only.\nREM # If you're on a mac or linux, just run `ant build` from this folder in Terminal\n\nset MYDIR=%~dp0\nset ANT_OPTS=-D\"file.encoding=UTF-8\"\nant build"
  },
  {
    "path": "build/tools/csslint-rhino.js",
    "content": "/*! \nCSSLint\nCopyright (c) 2011 Nicole Sullivan and Nicholas C. Zakas. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n/* Build time: 5-July-2011 03:16:53 */\nvar CSSLint = (function(){\n/*!\nParser-Lib\nCopyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n/* Build time: 5-July-2011 03:12:40 */\nvar parserlib = {};\n(function(){\n\n/**\n * A generic base to inherit from for any object\n * that needs event handling.\n * @class EventTarget\n * @constructor\n */\nfunction EventTarget(){\n\n    /**\n     * The array of listeners for various events.\n     * @type Object\n     * @property _listeners\n     * @private\n     */\n    this._listeners = {};    \n}\n\nEventTarget.prototype = {\n\n    //restore constructor\n    constructor: EventTarget,\n\n    /**\n     * Adds a listener for a given event type.\n     * @param {String} type The type of event to add a listener for.\n     * @param {Function} listener The function to call when the event occurs.\n     * @return {void}\n     * @method addListener\n     */\n    addListener: function(type, listener){\n        if (!this._listeners[type]){\n            this._listeners[type] = [];\n        }\n\n        this._listeners[type].push(listener);\n    },\n    \n    /**\n     * Fires an event based on the passed-in object.\n     * @param {Object|String} event An object with at least a 'type' attribute\n     *      or a string indicating the event name.\n     * @return {void}\n     * @method fire\n     */    \n    fire: function(event){\n        if (typeof event == \"string\"){\n            event = { type: event };\n        }\n        if (!event.target){\n            event.target = this;\n        }\n        \n        if (!event.type){\n            throw new Error(\"Event object missing 'type' property.\");\n        }\n        \n        if (this._listeners[event.type]){\n        \n            //create a copy of the array and use that so listeners can't chane\n            var listeners = this._listeners[event.type].concat();\n            for (var i=0, len=listeners.length; i < len; i++){\n                listeners[i].call(this, event);\n            }\n        }            \n    },\n\n    /**\n     * Removes a listener for a given event type.\n     * @param {String} type The type of event to remove a listener from.\n     * @param {Function} listener The function to remove from the event.\n     * @return {void}\n     * @method removeListener\n     */\n    removeListener: function(type, listener){\n        if (this._listeners[type]){\n            var listeners = this._listeners[type];\n            for (var i=0, len=listeners.length; i < len; i++){\n                if (listeners[i] === listener){\n                    listeners.splice(i, 1);\n                    break;\n                }\n            }\n            \n            \n        }            \n    }\n};\n/**\n * Convenient way to read through strings.\n * @namespace parserlib.util\n * @class StringReader\n * @constructor\n * @param {String} text The text to read.\n */\nfunction StringReader(text){\n    \n    /**\n     * The input text with line endings normalized.\n     * @property _input\n     * @type String\n     * @private\n     */\n    this._input = text.replace(/\\n\\r?/g, \"\\n\");\n    \n    \n    /**\n     * The row for the character to be read next.\n     * @property _line\n     * @type int\n     * @private\n     */\n    this._line = 1;\n    \n    \n    /**\n     * The column for the character to be read next.\n     * @property _col\n     * @type int\n     * @private\n     */\n    this._col = 1;\n    \n    /**\n     * The index of the character in the input to be read next.\n     * @property _cursor\n     * @type int\n     * @private\n     */    \n    this._cursor = 0;\n}\n\nStringReader.prototype = {\n\n    //restore constructor\n    constructor: StringReader,\n        \n    //-------------------------------------------------------------------------\n    // Position info\n    //-------------------------------------------------------------------------\n    \n    /**\n     * Returns the column of the character to be read next.\n     * @return {int} The column of the character to be read next.\n     * @method getCol\n     */\n    getCol: function(){\n        return this._col;\n    },\n    \n    /**\n     * Returns the row of the character to be read next.\n     * @return {int} The row of the character to be read next.\n     * @method getLine\n     */    \n    getLine: function(){\n        return this._line ;\n    },\n    \n    /**\n     * Determines if you're at the end of the input.\n     * @return {Boolean} True if there's no more input, false otherwise.\n     * @method eof\n     */    \n    eof: function(){\n        return (this._cursor == this._input.length)\n    },\n    \n    //-------------------------------------------------------------------------\n    // Basic reading\n    //-------------------------------------------------------------------------\n    \n    /**\n     * Reads the next character without advancing the cursor.\n     * @param {int} count How many characters to look ahead (default is 1).\n     * @return {String} The next character or null if there is no next character.\n     * @method peek\n     */\n    peek: function(count){\n        var c = null;\n        count = (typeof count == \"undefined\" ? 1 : count);\n        \n        //if we're not at the end of the input...\n        if (this._cursor < this._input.length){        \n        \n            //get character and increment cursor and column\n            c = this._input.charAt(this._cursor + count - 1);\n        }\n        \n        return c;\n    },        \n       \n    /**\n     * Reads the next character from the input and adjusts the row and column\n     * accordingly.\n     * @return {String} The next character or null if there is no next character.\n     * @method read\n     */\n    read: function(){\n        var c = null;\n        \n        //if we're not at the end of the input...\n        if (this._cursor < this._input.length){\n        \n            //if the last character was a newline, increment row count\n            //and reset column count\n            if (this._input.charAt(this._cursor) == \"\\n\"){\n                this._line++;\n                this._col=1;\n            } else {\n                this._col++;\n            }\n        \n            //get character and increment cursor and column\n            c = this._input.charAt(this._cursor++);\n        }\n        \n        return c;\n    },        \n       \n    //-------------------------------------------------------------------------\n    // Misc\n    //-------------------------------------------------------------------------\n    \n    /**\n     * Saves the current location so it can be returned to later.\n     * @method mark\n     * @return {void}\n     */\n    mark: function(){\n        this._bookmark = {\n            cursor: this._cursor,\n            line:   this._line,\n            col:    this._col\n        };\n    },\n    \n    reset: function(){\n        if (this._bookmark){\n            this._cursor = this._bookmark.cursor;\n            this._line = this._bookmark.line;\n            this._col = this._bookmark.col;\n            delete this._bookmark;\n        }\n    },\n    \n    //-------------------------------------------------------------------------\n    // Advanced reading\n    //-------------------------------------------------------------------------\n    \n    /**\n     * Reads up to and including the given string. Throws an error if that\n     * string is not found.\n     * @param {String} pattern The string to read.\n     * @return {String} The string when it is found.\n     * @throws Error when the string pattern is not found.\n     * @method readTo\n     */       \n    readTo: function(pattern){\n    \n        var buffer = \"\",\n            c;\n\n        /*\n         * First, buffer must be the same length as the pattern.\n         * Then, buffer must end with the pattern or else reach the\n         * end of the input.\n         */\n        while (buffer.length < pattern.length || buffer.lastIndexOf(pattern) != buffer.length - pattern.length){\n            c = this.read();\n            if (c){\n                buffer += c;\n            } else {\n                throw new Error(\"Expected \\\"\" + pattern + \"\\\" at line \" + this._line  + \", col \" + this._col + \".\");\n            }\n        }\n        \n        return buffer;\n    \n    },\n    \n    /**\n     * Reads characters while each character causes the given\n     * filter function to return true. The function is passed\n     * in each character and either returns true to continue\n     * reading or false to stop.\n     * @param {Function} filter The function to read on each character.\n     * @return {String} The string made up of all characters that passed the\n     *      filter check.\n     * @method readWhile\n     */           \n    readWhile: function(filter){\n        \n        var buffer = \"\",\n            c = this.read();\n        \n        while(c !== null && filter(c)){\n            buffer += c;\n            c = this.read();\n        }\n        \n        return buffer;\n    \n    },\n    \n    /**\n     * Reads characters that match either text or a regular expression and\n     * returns those characters. If a match is found, the row and column\n     * are adjusted; if no match is found, the reader's state is unchanged.\n     * reading or false to stop.\n     * @param {String|RegExp} matchter If a string, then the literal string\n     *      value is searched for. If a regular expression, then any string\n     *      matching the pattern is search for.\n     * @return {String} The string made up of all characters that matched or\n     *      null if there was no match.\n     * @method readMatch\n     */               \n    readMatch: function(matcher){\n    \n        var source = this._input.substring(this._cursor),\n            value = null;\n        \n        //if it's a string, just do a straight match\n        if (typeof matcher == \"string\"){\n            if (source.indexOf(matcher) === 0){\n                value = this.readCount(matcher.length); \n            }\n        } else if (matcher instanceof RegExp){\n            if (matcher.test(source)){\n                value = this.readCount(RegExp.lastMatch.length);\n            }\n        }\n        \n        return value;        \n    },\n    \n    \n    /**\n     * Reads a given number of characters. If the end of the input is reached,\n     * it reads only the remaining characters and does not throw an error.\n     * @param {int} count The number of characters to read.\n     * @return {String} The string made up the read characters.\n     * @method readCount\n     */                   \n    readCount: function(count){\n        var buffer = \"\";\n        \n        while(count--){\n            buffer += this.read();\n        }\n        \n        return buffer;\n    }\n\n};\n/**\n * Type to use when a syntax error occurs.\n * @class SyntaxError\n * @namespace parserlib.util\n * @constructor\n * @param {String} message The error message.\n * @param {int} line The line at which the error occurred.\n * @param {int} col The column at which the error occurred.\n */\nfunction SyntaxError(message, line, col){\n\n    /**\n     * The column at which the error occurred.\n     * @type int\n     * @property col\n     */\n    this.col = col;\n\n    /**\n     * The line at which the error occurred.\n     * @type int\n     * @property line\n     */\n    this.line = line;\n\n    /**\n     * The text representation of the unit.\n     * @type String\n     * @property text\n     */\n    this.message = message;\n\n}\n\n//inherit from Error\nSyntaxError.prototype = new Error();\n/**\n * Base type to represent a single syntactic unit.\n * @class SyntaxUnit\n * @namespace parserlib.util\n * @constructor\n * @param {String} text The text of the unit.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction SyntaxUnit(text, line, col){\n\n\n    /**\n     * The column of text on which the unit resides.\n     * @type int\n     * @property col\n     */\n    this.col = col;\n\n    /**\n     * The line of text on which the unit resides.\n     * @type int\n     * @property line\n     */\n    this.line = line;\n\n    /**\n     * The text representation of the unit.\n     * @type String\n     * @property text\n     */\n    this.text = text;\n\n}\n\n/**\n * Create a new syntax unit based solely on the given token.\n * Convenience method for creating a new syntax unit when\n * it represents a single token instead of multiple.\n * @param {Object} token The token object to represent.\n * @return {parserlib.util.SyntaxUnit} The object representing the token.\n * @static\n * @method fromToken\n */\nSyntaxUnit.fromToken = function(token){\n    return new SyntaxUnit(token.value, token.startLine, token.startCol);\n};\n\nSyntaxUnit.prototype = {\n\n    //restore constructor\n    constructor: SyntaxUnit,\n    \n    /**\n     * Returns the text representation of the unit.\n     * @return {String} The text representation of the unit.\n     * @method valueOf\n     */\n    valueOf: function(){\n        return this.toString();\n    },\n    \n    /**\n     * Returns the text representation of the unit.\n     * @return {String} The text representation of the unit.\n     * @method toString\n     */\n    toString: function(){\n        return this.text;\n    }\n\n};\n/**\n * Generic TokenStream providing base functionality.\n * @class TokenStreamBase\n * @namespace parserlib.util\n * @constructor\n * @param {String|StringReader} input The text to tokenize or a reader from \n *      which to read the input.\n */\nfunction TokenStreamBase(input, tokenData){\n\n    /**\n     * The string reader for easy access to the text.\n     * @type StringReader\n     * @property _reader\n     * @private\n     */\n    //this._reader = (typeof input == \"string\") ? new StringReader(input) : input;\n    this._reader = input ? new StringReader(input.toString()) : null;\n    \n    /**\n     * Token object for the last consumed token.\n     * @type Token\n     * @property _token\n     * @private\n     */\n    this._token = null;    \n    \n    /**\n     * The array of token information.\n     * @type Array\n     * @property _tokenData\n     * @private\n     */\n    this._tokenData = tokenData;\n    \n    /**\n     * Lookahead token buffer.\n     * @type Array\n     * @property _lt\n     * @private\n     */\n    this._lt = [];\n    \n    /**\n     * Lookahead token buffer index.\n     * @type int\n     * @property _ltIndex\n     * @private\n     */\n    this._ltIndex = 0;\n    \n    this._ltIndexCache = [];\n}\n\n/**\n * Accepts an array of token information and outputs\n * an array of token data containing key-value mappings\n * and matching functions that the TokenStream needs.\n * @param {Array} tokens An array of token descriptors.\n * @return {Array} An array of processed token data.\n * @method createTokenData\n * @static\n */\nTokenStreamBase.createTokenData = function(tokens){\n\n    var nameMap \t= [],\n        typeMap \t= {},\n\t\ttokenData \t= tokens.concat([]),\n\t\ti\t\t\t= 0,\n\t\tlen\t\t\t= tokenData.length+1;\n    \n    tokenData.UNKNOWN = -1;\n\ttokenData.unshift({name:\"EOF\"});\n\n    for (; i < len; i++){\n        nameMap.push(tokenData[i].name);\n        tokenData[tokenData[i].name] = i;\n        if (tokenData[i].text){\n            typeMap[tokenData[i].text] = i;\n        }\n    }\n    \n    tokenData.name = function(tt){\n        return nameMap[tt];\n    };\n    \n    tokenData.type = function(c){\n        return typeMap[c];\n    };\n\t\n\treturn tokenData;\n};\n\nTokenStreamBase.prototype = {\n\n    //restore constructor\n    constructor: TokenStreamBase,    \n    \n    //-------------------------------------------------------------------------\n    // Matching methods\n    //-------------------------------------------------------------------------\n    \n    /**\n     * Determines if the next token matches the given token type.\n     * If so, that token is consumed; if not, the token is placed\n     * back onto the token stream. You can pass in any number of\n     * token types and this will return true if any of the token\n     * types is found.\n     * @param {int|int[]} tokenTypes Either a single token type or an array of\n     *      token types that the next token might be. If an array is passed,\n     *      it's assumed that the token can be any of these.\n     * @param {variant} channel (Optional) The channel to read from. If not\n     *      provided, reads from the default (unnamed) channel.\n     * @return {Boolean} True if the token type matches, false if not.\n     * @method match\n     */\n    match: function(tokenTypes, channel){\n    \n        //always convert to an array, makes things easier\n        if (!(tokenTypes instanceof Array)){\n            tokenTypes = [tokenTypes];\n        }\n                \n        var tt  = this.get(channel),\n            i   = 0,\n            len = tokenTypes.length;\n            \n        while(i < len){\n            if (tt == tokenTypes[i++]){\n                return true;\n            }\n        }\n        \n        //no match found, put the token back\n        this.unget();\n        return false;\n    },    \n    \n    /**\n     * Determines if the next token matches the given token type.\n     * If so, that token is consumed; if not, an error is thrown.\n     * @param {int|int[]} tokenTypes Either a single token type or an array of\n     *      token types that the next token should be. If an array is passed,\n     *      it's assumed that the token must be one of these.\n     * @param {variant} channel (Optional) The channel to read from. If not\n     *      provided, reads from the default (unnamed) channel.\n     * @return {void}\n     * @method mustMatch\n     */    \n    mustMatch: function(tokenTypes, channel){\n\n        //always convert to an array, makes things easier\n        if (!(tokenTypes instanceof Array)){\n            tokenTypes = [tokenTypes];\n        }\n\n        if (!this.match.apply(this, arguments)){    \n            token = this.LT(1);\n            throw new SyntaxError(\"Expected \" + this._tokenData[tokenTypes[0]].name + \n                \" at line \" + token.startLine + \", character \" + token.startCol + \".\", token.startLine, token.startCol);\n        }\n    },\n    \n    //-------------------------------------------------------------------------\n    // Consuming methods\n    //-------------------------------------------------------------------------\n    \n    /**\n     * Keeps reading from the token stream until either one of the specified\n     * token types is found or until the end of the input is reached.\n     * @param {int|int[]} tokenTypes Either a single token type or an array of\n     *      token types that the next token should be. If an array is passed,\n     *      it's assumed that the token must be one of these.\n     * @param {variant} channel (Optional) The channel to read from. If not\n     *      provided, reads from the default (unnamed) channel.\n     * @return {void}\n     * @method advance\n     */\n    advance: function(tokenTypes, channel){\n        \n        while(this.LA(0) != 0 && !this.match(tokenTypes, channel)){\n            this.get();\n        }\n\n        return this.LA(0);    \n    },\n    \n    /**\n     * Consumes the next token from the token stream. \n     * @return {int} The token type of the token that was just consumed.\n     * @method get\n     */      \n    get: function(channel){\n    \n        var tokenInfo   = this._tokenData,\n            reader      = this._reader,\n            value,\n            i           =0,\n            len         = tokenInfo.length,\n            found       = false,\n            token,\n            info;\n            \n        //check the lookahead buffer first\n        if (this._lt.length && this._ltIndex >= 0 && this._ltIndex < this._lt.length){  \n                           \n            i++;\n            this._token = this._lt[this._ltIndex++];\n            info = tokenInfo[this._token.type];\n            \n            //obey channels logic\n            while((info.channel !== undefined && channel !== info.channel) &&\n                    this._ltIndex < this._lt.length){\n                this._token = this._lt[this._ltIndex++];\n                info = tokenInfo[this._token.type];\n                i++;\n            }\n            \n            //here be dragons\n            if ((info.channel === undefined || channel === info.channel) &&\n                    this._ltIndex <= this._lt.length){\n                this._ltIndexCache.push(i);\n                return this._token.type;\n            }\n        }\n        \n        //call token retriever method\n\t\ttoken = this._getToken();\n\n        //if it should be hidden, don't save a token\n        if (token.type > -1 && !tokenInfo[token.type].hide){\n                     \n            //apply token channel\n            token.channel = tokenInfo[token.type].channel;\n         \n            //save for later\n            this._token = token;\n            this._lt.push(token);\n\n            //save space that will be moved (must be done before array is truncated)\n            this._ltIndexCache.push(this._lt.length - this._ltIndex + i);  \n        \n            //keep the buffer under 5 items\n            if (this._lt.length > 5){\n                this._lt.shift();                \n            }\n            \n            //also keep the shift buffer under 5 items\n            if (this._ltIndexCache.length > 5){\n                this._ltIndexCache.shift();\n            }\n                \n            //update lookahead index\n            this._ltIndex = this._lt.length;\n        }\n            \n        /*\n         * Skip to the next token if:\n         * 1. The token type is marked as hidden.\n         * 2. The token type has a channel specified and it isn't the current channel.\n         */\n        info = tokenInfo[token.type];\n        if (info && \n                (info.hide || \n                (info.channel !== undefined && channel !== info.channel))){\n            return this.get(channel);\n        } else {\n            //return just the type\n            return token.type;\n        }\n    },\n    \n    /**\n     * Looks ahead a certain number of tokens and returns the token type at\n     * that position. This will throw an error if you lookahead past the\n     * end of input, past the size of the lookahead buffer, or back past\n     * the first token in the lookahead buffer.\n     * @param {int} The index of the token type to retrieve. 0 for the\n     *      current token, 1 for the next, -1 for the previous, etc.\n     * @return {int} The token type of the token in the given position.\n     * @method LA\n     */\n    LA: function(index){\n        var total = index,\n            tt;\n        if (index > 0){\n            //TODO: Store 5 somewhere\n            if (index > 5){\n                throw new Error(\"Too much lookahead.\");\n            }\n        \n            //get all those tokens\n            while(total){\n                tt = this.get();   \n                total--;                            \n            }\n            \n            //unget all those tokens\n            while(total < index){\n                this.unget();\n                total++;\n            }\n        } else if (index < 0){\n        \n            if(this._lt[this._ltIndex+index]){\n                tt = this._lt[this._ltIndex+index].type;\n            } else {\n                throw new Error(\"Too much lookbehind.\");\n            }\n        \n        } else {\n            tt = this._token.type;\n        }\n        \n        return tt;\n    \n    },\n    \n    /**\n     * Looks ahead a certain number of tokens and returns the token at\n     * that position. This will throw an error if you lookahead past the\n     * end of input, past the size of the lookahead buffer, or back past\n     * the first token in the lookahead buffer.\n     * @param {int} The index of the token type to retrieve. 0 for the\n     *      current token, 1 for the next, -1 for the previous, etc.\n     * @return {Object} The token of the token in the given position.\n     * @method LA\n     */    \n    LT: function(index){\n    \n        //lookahead first to prime the token buffer\n        this.LA(index);\n        \n        //now find the token, subtract one because _ltIndex is already at the next index\n        return this._lt[this._ltIndex+index-1];    \n    },\n    \n    /**\n     * Returns the token type for the next token in the stream without \n     * consuming it.\n     * @return {int} The token type of the next token in the stream.\n     * @method peek\n     */\n    peek: function(){\n        return this.LA(1);\n    },\n    \n    /**\n     * Returns the actual token object for the last consumed token.\n     * @return {Token} The token object for the last consumed token.\n     * @method token\n     */\n    token: function(){\n        return this._token;\n    },\n    \n    /**\n     * Returns the name of the token for the given token type.\n     * @param {int} tokenType The type of token to get the name of.\n     * @return {String} The name of the token or \"UNKNOWN_TOKEN\" for any\n     *      invalid token type.\n     * @method tokenName\n     */\n    tokenName: function(tokenType){\n        if (tokenType < 0 || tokenType > this._tokenData.length){\n            return \"UNKNOWN_TOKEN\";\n        } else {\n            return this._tokenData[tokenType].name;\n        }\n    },\n    \n    /**\n     * Returns the token type value for the given token name.\n     * @param {String} tokenName The name of the token whose value should be returned.\n     * @return {int} The token type value for the given token name or -1\n     *      for an unknown token.\n     * @method tokenName\n     */    \n    tokenType: function(tokenName){\n        return this._tokenData[tokenName] || -1;\n    },\n    \n    /**\n     * Returns the last consumed token to the token stream.\n     * @method unget\n     */      \n    unget: function(){\n        //if (this._ltIndex > -1){\n        if (this._ltIndexCache.length){\n            this._ltIndex -= this._ltIndexCache.pop();//--;\n            this._token = this._lt[this._ltIndex - 1];\n        } else {\n            throw new Error(\"Too much lookahead.\");\n        }\n    }\n\n};\n\n\nparserlib.util = {\nStringReader: StringReader,\nSyntaxError : SyntaxError,\nSyntaxUnit  : SyntaxUnit,\nEventTarget : EventTarget,\nTokenStreamBase : TokenStreamBase\n};\n})();\n/* \nParser-Lib\nCopyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n/* Build time: 5-July-2011 03:12:40 */\n(function(){\nvar EventTarget = parserlib.util.EventTarget,\nTokenStreamBase = parserlib.util.TokenStreamBase,\nStringReader = parserlib.util.StringReader,\nSyntaxError = parserlib.util.SyntaxError,\nSyntaxUnit  = parserlib.util.SyntaxUnit;\n\nvar Colors = {\n    aliceblue       :\"#f0f8ff\",\n    antiquewhite    :\"#faebd7\",\n    aqua            :\"#00ffff\",\n    aquamarine      :\"#7fffd4\",\n    azure           :\"#f0ffff\",\n    beige           :\"#f5f5dc\",\n    bisque          :\"#ffe4c4\",\n    black           :\"#000000\",\n    blanchedalmond  :\"#ffebcd\",\n    blue            :\"#0000ff\",\n    blueviolet      :\"#8a2be2\",\n    brown           :\"#a52a2a\",\n    burlywood       :\"#deb887\",\n    cadetblue       :\"#5f9ea0\",\n    chartreuse      :\"#7fff00\",\n    chocolate       :\"#d2691e\",\n    coral           :\"#ff7f50\",\n    cornflowerblue  :\"#6495ed\",\n    cornsilk        :\"#fff8dc\",\n    crimson         :\"#dc143c\",\n    cyan            :\"#00ffff\",\n    darkblue        :\"#00008b\",\n    darkcyan        :\"#008b8b\",\n    darkgoldenrod   :\"#b8860b\",\n    darkgray        :\"#a9a9a9\",\n    darkgreen       :\"#006400\",\n    darkkhaki       :\"#bdb76b\",\n    darkmagenta     :\"#8b008b\",\n    darkolivegreen  :\"#556b2f\",\n    darkorange      :\"#ff8c00\",\n    darkorchid      :\"#9932cc\",\n    darkred         :\"#8b0000\",\n    darksalmon      :\"#e9967a\",\n    darkseagreen    :\"#8fbc8f\",\n    darkslateblue   :\"#483d8b\",\n    darkslategray   :\"#2f4f4f\",\n    darkturquoise   :\"#00ced1\",\n    darkviolet      :\"#9400d3\",\n    deeppink        :\"#ff1493\",\n    deepskyblue     :\"#00bfff\",\n    dimgray         :\"#696969\",\n    dodgerblue      :\"#1e90ff\",\n    firebrick       :\"#b22222\",\n    floralwhite     :\"#fffaf0\",\n    forestgreen     :\"#228b22\",\n    fuchsia         :\"#ff00ff\",\n    gainsboro       :\"#dcdcdc\",\n    ghostwhite      :\"#f8f8ff\",\n    gold            :\"#ffd700\",\n    goldenrod       :\"#daa520\",\n    gray            :\"#808080\",\n    green           :\"#008000\",\n    greenyellow     :\"#adff2f\",\n    honeydew        :\"#f0fff0\",\n    hotpink         :\"#ff69b4\",\n    indianred       :\"#cd5c5c\",\n    indigo          :\"#4b0082\",\n    ivory           :\"#fffff0\",\n    khaki           :\"#f0e68c\",\n    lavender        :\"#e6e6fa\",\n    lavenderblush   :\"#fff0f5\",\n    lawngreen       :\"#7cfc00\",\n    lemonchiffon    :\"#fffacd\",\n    lightblue       :\"#add8e6\",\n    lightcoral      :\"#f08080\",\n    lightcyan       :\"#e0ffff\",\n    lightgoldenrodyellow  :\"#fafad2\",\n    lightgrey       :\"#d3d3d3\",\n    lightgreen      :\"#90ee90\",\n    lightpink       :\"#ffb6c1\",\n    lightsalmon     :\"#ffa07a\",\n    lightseagreen   :\"#20b2aa\",\n    lightskyblue    :\"#87cefa\",\n    lightslategray  :\"#778899\",\n    lightsteelblue  :\"#b0c4de\",\n    lightyellow     :\"#ffffe0\",\n    lime            :\"#00ff00\",\n    limegreen       :\"#32cd32\",\n    linen           :\"#faf0e6\",\n    magenta         :\"#ff00ff\",\n    maroon          :\"#800000\",\n    mediumaquamarine:\"#66cdaa\",\n    mediumblue      :\"#0000cd\",\n    mediumorchid    :\"#ba55d3\",\n    mediumpurple    :\"#9370d8\",\n    mediumseagreen  :\"#3cb371\",\n    mediumslateblue :\"#7b68ee\",\n    mediumspringgreen   :\"#00fa9a\",\n    mediumturquoise :\"#48d1cc\",\n    mediumvioletred :\"#c71585\",\n    midnightblue    :\"#191970\",\n    mintcream       :\"#f5fffa\",\n    mistyrose       :\"#ffe4e1\",\n    moccasin        :\"#ffe4b5\",\n    navajowhite     :\"#ffdead\",\n    navy            :\"#000080\",\n    oldlace         :\"#fdf5e6\",\n    olive           :\"#808000\",\n    olivedrab       :\"#6b8e23\",\n    orange          :\"#ffa500\",\n    orangered       :\"#ff4500\",\n    orchid          :\"#da70d6\",\n    palegoldenrod   :\"#eee8aa\",\n    palegreen       :\"#98fb98\",\n    paleturquoise   :\"#afeeee\",\n    palevioletred   :\"#d87093\",\n    papayawhip      :\"#ffefd5\",\n    peachpuff       :\"#ffdab9\",\n    peru            :\"#cd853f\",\n    pink            :\"#ffc0cb\",\n    plum            :\"#dda0dd\",\n    powderblue      :\"#b0e0e6\",\n    purple          :\"#800080\",\n    red             :\"#ff0000\",\n    rosybrown       :\"#bc8f8f\",\n    royalblue       :\"#4169e1\",\n    saddlebrown     :\"#8b4513\",\n    salmon          :\"#fa8072\",\n    sandybrown      :\"#f4a460\",\n    seagreen        :\"#2e8b57\",\n    seashell        :\"#fff5ee\",\n    sienna          :\"#a0522d\",\n    silver          :\"#c0c0c0\",\n    skyblue         :\"#87ceeb\",\n    slateblue       :\"#6a5acd\",\n    slategray       :\"#708090\",\n    snow            :\"#fffafa\",\n    springgreen     :\"#00ff7f\",\n    steelblue       :\"#4682b4\",\n    tan             :\"#d2b48c\",\n    teal            :\"#008080\",\n    thistle         :\"#d8bfd8\",\n    tomato          :\"#ff6347\",\n    turquoise       :\"#40e0d0\",\n    violet          :\"#ee82ee\",\n    wheat           :\"#f5deb3\",\n    white           :\"#ffffff\",\n    whitesmoke      :\"#f5f5f5\",\n    yellow          :\"#ffff00\",\n    yellowgreen     :\"#9acd32\"\n};\n/**\n * Represents a selector combinator (whitespace, +, >).\n * @namespace parserlib.css\n * @class Combinator\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {String} text The text representation of the unit. \n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction Combinator(text, line, col){\n    \n    SyntaxUnit.call(this, text, line, col);\n\n    /**\n     * The type of modifier.\n     * @type String\n     * @property type\n     */\n    this.type = \"unknown\";\n    \n    //pretty simple\n    if (/^\\s+$/.test(text)){\n        this.type = \"descendant\";\n    } else if (text == \">\"){\n        this.type = \"child\";\n    } else if (text == \"+\"){\n        this.type = \"adjacent-sibling\";\n    } else if (text == \"~\"){\n        this.type = \"sibling\";\n    }\n\n}\n\nCombinator.prototype = new SyntaxUnit();\nCombinator.prototype.constructor = Combinator;\n\n\nvar Level1Properties = {\n\n    \"background\": 1,\n    \"background-attachment\": 1,\n    \"background-color\": 1,\n    \"background-image\": 1,\n    \"background-position\": 1,\n    \"background-repeat\": 1,\n \n    \"border\": 1,\n    \"border-bottom\": 1,\n    \"border-bottom-width\": 1,\n    \"border-color\": 1,\n    \"border-left\": 1,\n    \"border-left-width\": 1,\n    \"border-right\": 1,\n    \"border-right-width\": 1,\n    \"border-style\": 1,\n    \"border-top\": 1,\n    \"border-top-width\": 1,\n    \"border-width\": 1,\n \n    \"clear\": 1,\n    \"color\": 1,\n    \"display\": 1,\n    \"float\": 1,\n \n    \"font\": 1,\n    \"font-family\": 1,\n    \"font-size\": 1,\n    \"font-style\": 1,\n    \"font-variant\": 1,\n    \"font-weight\": 1,\n \n    \"height\": 1,\n    \"letter-spacing\": 1,\n    \"line-height\": 1,\n \n    \"list-style\": 1,\n    \"list-style-image\": 1,\n    \"list-style-position\": 1,\n    \"list-style-type\": 1,\n \n    \"margin\": 1,\n    \"margin-bottom\": 1,\n    \"margin-left\": 1,\n    \"margin-right\": 1,\n    \"margin-top\": 1,\n \n    \"padding\": 1,\n    \"padding-bottom\": 1,\n    \"padding-left\": 1,\n    \"padding-right\": 1,\n    \"padding-top\": 1,\n \n    \"text-align\": 1,\n    \"text-decoration\": 1,\n    \"text-indent\": 1,\n    \"text-transform\": 1,\n \n    \"vertical-align\": 1,\n    \"white-space\": 1,\n    \"width\": 1,\n    \"word-spacing\": 1\n    \n};\n\nvar Level2Properties = {\n\n    //Aural\n    \"azimuth\": 1,\n    \"cue-after\": 1,\n    \"cue-before\": 1,\n    \"cue\": 1,\n    \"elevation\": 1,\n    \"pause-after\": 1,\n    \"pause-before\": 1,\n    \"pause\": 1,\n    \"pitch-range\": 1,\n    \"pitch\": 1,\n    \"play-during\": 1,\n    \"richness\": 1,\n    \"speak-header\": 1,\n    \"speak-numeral\": 1,\n    \"speak-punctuation\": 1,\n    \"speak\": 1,\n    \"speech-rate\": 1,\n    \"stress\": 1,\n    \"voice-family\": 1,\n    \"volume\": 1,\n    \n    //Paged\n    \"orphans\": 1,\n    \"page-break-after\": 1,\n    \"page-break-before\": 1,\n    \"page-break-inside\": 1,\n    \"widows\": 1,\n\n    //Interactive\n    \"cursor\": 1,\n    \"outline-color\": 1,\n    \"outline-style\": 1,\n    \"outline-width\": 1,\n    \"outline\": 1,    \n    \n    //Visual\n    \"background-attachment\": 1,\n    \"background-color\": 1,\n    \"background-image\": 1,\n    \"background-position\": 1,\n    \"background-repeat\": 1,\n    \"background\": 1,    \n    \"border-collapse\": 1,\n    \"border-color\": 1,\n    \"border-spacing\": 1,\n    \"border-style\": 1,\n    \"border-top\": 1,\n    \"border-top-color\": 1,\n    \"border-top-style\": 1,\n    \"border-top-width\": 1,\n    \"border-width\": 1,\n    \"border\": 1,\n    \"bottom\": 1,    \n    \"caption-side\": 1,\n    \"clear\": 1,\n    \"clip\": 1,\n    \"color\": 1,\n    \"content\": 1,\n    \"counter-increment\": 1,\n    \"counter-reset\": 1,\n    \"direction\": 1,\n    \"display\": 1,\n    \"empty-cells\": 1,\n    \"float\": 1,\n    \"font-family\": 1,\n    \"font-size\": 1,\n    \"font-style\": 1,\n    \"font-variant\": 1,\n    \"font-weight\": 1,\n    \"font\": 1,\n    \"height\": 1,\n    \"left\": 1,\n    \"letter-spacing\": 1,\n    \"line-height\": 1,\n    \"list-style-image\": 1,\n    \"list-style-position\": 1,\n    \"list-style-type\": 1,\n    \"list-style\": 1,\n    \"margin-right\": 1,\n    \"margin-top\": 1,\n    \"margin\": 1,\n    \"max-height\": 1,\n    \"max-width\": 1,\n    \"min-height\": 1,\n    \"min-width\": 1,\n    \"overflow\": 1,\n    \"padding-top\": 1,\n    \"padding\": 1,\n    \"position\": 1,\n    \"quotes\": 1,\n    \"right\": 1,\n    \"table-layout\": 1,\n    \"text-align\": 1,\n    \"text-decoration\": 1,\n    \"text-indent\": 1,\n    \"text-transform\": 1,\n    \"top\": 1,\n    \"unicode-bidi\": 1,\n    \"vertical-align\": 1,\n    \"visibility\": 1,\n    \"white-space\": 1,\n    \"width\": 1,\n    \"word-spacing\": 1,\n    \"z-index\": 1\n};\n/**\n * Represents a media feature, such as max-width:500.\n * @namespace parserlib.css\n * @class MediaFeature\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {SyntaxUnit} name The name of the feature.\n * @param {SyntaxUnit} value The value of the feature or null if none.\n */\nfunction MediaFeature(name, value){\n    \n    SyntaxUnit.call(this, \"(\" + name + (value !== null ? \":\" + value : \"\") + \")\", name.startLine, name.startCol);\n\n    /**\n     * The name of the media feature\n     * @type String\n     * @property name\n     */\n    this.name = name;\n\n    /**\n     * The value for the feature or null if there is none.\n     * @type SyntaxUnit\n     * @property value\n     */\n    this.value = value;\n}\n\nMediaFeature.prototype = new SyntaxUnit();\nMediaFeature.prototype.constructor = MediaFeature;\n\n/**\n * Represents an individual media query.\n * @namespace parserlib.css\n * @class MediaQuery\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {String} modifier The modifier \"not\" or \"only\" (or null).\n * @param {String} mediaType The type of media (i.e., \"print\").\n * @param {Array} parts Array of selectors parts making up this selector.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction MediaQuery(modifier, mediaType, features, line, col){\n    \n    SyntaxUnit.call(this, (modifier ? modifier + \" \": \"\") + (mediaType ? mediaType + \" \" : \"\") + features.join(\" and \"), line, col);\n\n    /**\n     * The media modifier (\"not\" or \"only\")\n     * @type String\n     * @property modifier\n     */\n    this.modifier = modifier;\n\n    /**\n     * The mediaType (i.e., \"print\")\n     * @type String\n     * @property mediaType\n     */\n    this.mediaType = mediaType;    \n    \n    /**\n     * The parts that make up the selector.\n     * @type Array\n     * @property features\n     */\n    this.features = features;\n\n}\n\nMediaQuery.prototype = new SyntaxUnit();\nMediaQuery.prototype.constructor = MediaQuery;\n\n/**\n * A CSS3 parser.\n * @namespace parserlib.css\n * @class Parser\n * @constructor\n * @param {Object} options (Optional) Various options for the parser:\n *      starHack (true|false) to allow IE6 star hack as valid,\n *      underscoreHack (true|false) to interpret leading underscores\n *      as IE6-7 targeting for known properties, ieFilters (true|false)\n *      to indicate that IE < 8 filters should be accepted and not throw\n *      syntax errors.\n */\nfunction Parser(options){\n\n    //inherit event functionality\n    EventTarget.call(this);\n\n\n    this.options = options || {};\n\n    this._tokenStream = null;\n}\n\nParser.prototype = function(){\n\n    var proto = new EventTarget(),  //new prototype\n        prop,\n        additions =  {\n        \n            //restore constructor\n            constructor: Parser,\n        \n            //-----------------------------------------------------------------\n            // Grammar\n            //-----------------------------------------------------------------\n        \n            _stylesheet: function(){\n            \n                /*\n                 * stylesheet\n                 *  : [ CHARSET_SYM S* STRING S* ';' ]?\n                 *    [S|CDO|CDC]* [ import [S|CDO|CDC]* ]*\n                 *    [ namespace [S|CDO|CDC]* ]*\n                 *    [ [ ruleset | media | page | font_face ] [S|CDO|CDC]* ]*\n                 *  ;\n                 */ \n               \n                var tokenStream = this._tokenStream,\n                    charset     = null,\n                    token,\n                    tt;\n                    \n                this.fire(\"startstylesheet\");\n            \n                //try to read character set\n                this._charset();\n                \n                this._skipCruft();\n\n                //try to read imports - may be more than one\n                while (tokenStream.peek() == Tokens.IMPORT_SYM){\n                    this._import();\n                    this._skipCruft();\n                }\n                \n                //try to read namespaces - may be more than one\n                while (tokenStream.peek() == Tokens.NAMESPACE_SYM){\n                    this._namespace();\n                    this._skipCruft();\n                }\n                \n                //get the next token\n                tt = tokenStream.peek();\n                \n                //try to read the rest\n                while(tt > Tokens.EOF){\n                \n                    try {\n                \n                        switch(tt){\n                            case Tokens.MEDIA_SYM:\n                                this._media();\n                                this._skipCruft();\n                                break;\n                            case Tokens.PAGE_SYM:\n                                this._page(); \n                                this._skipCruft();\n                                break;                   \n                            case Tokens.FONT_FACE_SYM:\n                                this._font_face(); \n                                this._skipCruft();\n                                break;  \n                            case Tokens.S:\n                                this._readWhitespace();\n                                break;\n                            default:                            \n                                if(!this._ruleset()){\n                                \n                                    //error handling for known issues\n                                    switch(tt){\n                                        case Tokens.CHARSET_SYM:\n                                            token = tokenStream.LT(1);\n                                            this._charset(false);\n                                            throw new SyntaxError(\"@charset not allowed here.\", token.startLine, token.startCol);\n                                        case Tokens.IMPORT_SYM:\n                                            token = tokenStream.LT(1);\n                                            this._import(false);\n                                            throw new SyntaxError(\"@import not allowed here.\", token.startLine, token.startCol);\n                                        case Tokens.NAMESPACE_SYM:\n                                            token = tokenStream.LT(1);\n                                            this._namespace(false);\n                                            throw new SyntaxError(\"@namespace not allowed here.\", token.startLine, token.startCol);\n                                        default:\n                                            tokenStream.get();  //get the last token\n                                            this._unexpectedToken(tokenStream.token());\n                                    }\n                                \n                                }\n                        }\n                    } catch(ex) {\n                        if (ex instanceof SyntaxError && !this.options.strict){\n                            this.fire({\n                                type:       \"error\",\n                                error:      ex,\n                                message:    ex.message,\n                                line:       ex.line,\n                                col:        ex.col\n                            });                     \n                        } else {\n                            throw ex;\n                        }\n                    }\n                    \n                    tt = tokenStream.peek();\n                }\n                \n                if (tt != Tokens.EOF){\n                    this._unexpectedToken(tokenStream.token());\n                }\n            \n                this.fire(\"endstylesheet\");\n            },\n            \n            _charset: function(emit){\n                var tokenStream = this._tokenStream,\n                    charset,\n                    token,\n                    line,\n                    col;\n                    \n                if (tokenStream.match(Tokens.CHARSET_SYM)){\n                    line = tokenStream.token().startLine;\n                    col = tokenStream.token().startCol;\n                \n                    this._readWhitespace();\n                    tokenStream.mustMatch(Tokens.STRING);\n                    \n                    token = tokenStream.token();\n                    charset = token.value;\n                    \n                    this._readWhitespace();\n                    tokenStream.mustMatch(Tokens.SEMICOLON);\n                    \n                    if (emit !== false){\n                        this.fire({ \n                            type:   \"charset\",\n                            charset:charset,\n                            line:   line,\n                            col:    col\n                        });\n                    }\n                }            \n            },\n            \n            _import: function(emit){\n                /*\n                 * import\n                 *   : IMPORT_SYM S*\n                 *    [STRING|URI] S* media_query_list? ';' S*\n                 */    \n            \n                var tokenStream = this._tokenStream,\n                    tt,\n                    uri,\n                    importToken,\n                    mediaList   = [];\n                \n                //read import symbol\n                tokenStream.mustMatch(Tokens.IMPORT_SYM);\n                importToken = tokenStream.token();\n                this._readWhitespace();\n                \n                tokenStream.mustMatch([Tokens.STRING, Tokens.URI]);\n                \n                //grab the URI value\n                uri = tokenStream.token().value.replace(/(?:url\\()?[\"']([^\"']+)[\"']\\)?/, \"$1\");                \n\n                this._readWhitespace();\n                \n                mediaList = this._media_query_list();\n                \n                //must end with a semicolon\n                tokenStream.mustMatch(Tokens.SEMICOLON);\n                this._readWhitespace();\n                \n                if (emit !== false){\n                    this.fire({\n                        type:   \"import\",\n                        uri:    uri,\n                        media:  mediaList,\n                        line:   importToken.startLine,\n                        col:    importToken.startCol\n                    });\n                }\n        \n            },\n            \n            _namespace: function(emit){\n                /*\n                 * namespace\n                 *   : NAMESPACE_SYM S* [namespace_prefix S*]? [STRING|URI] S* ';' S*\n                 */    \n            \n                var tokenStream = this._tokenStream,\n                    line,\n                    col,\n                    prefix,\n                    uri;\n                \n                //read import symbol\n                tokenStream.mustMatch(Tokens.NAMESPACE_SYM);\n                line = tokenStream.token().startLine;\n                col = tokenStream.token().startCol;\n                this._readWhitespace();\n                \n                //it's a namespace prefix - no _namespace_prefix() method because it's just an IDENT\n                if (tokenStream.match(Tokens.IDENT)){\n                    prefix = tokenStream.token().value;\n                    this._readWhitespace();\n                }\n                \n                tokenStream.mustMatch([Tokens.STRING, Tokens.URI]);\n                /*if (!tokenStream.match(Tokens.STRING)){\n                    tokenStream.mustMatch(Tokens.URI);\n                }*/\n                \n                //grab the URI value\n                uri = tokenStream.token().value.replace(/(?:url\\()?[\"']([^\"']+)[\"']\\)?/, \"$1\");                \n\n                this._readWhitespace();\n\n                //must end with a semicolon\n                tokenStream.mustMatch(Tokens.SEMICOLON);\n                this._readWhitespace();\n                \n                if (emit !== false){\n                    this.fire({\n                        type:   \"namespace\",\n                        prefix: prefix,\n                        uri:    uri,\n                        line:   line,\n                        col:    col\n                    });\n                }\n        \n            },            \n                       \n            _media: function(){\n                /*\n                 * media\n                 *   : MEDIA_SYM S* media_query_list S* '{' S* ruleset* '}' S*\n                 *   ;\n                 */\n                var tokenStream     = this._tokenStream,\n                    line,\n                    col,\n                    mediaList;//       = [];\n                \n                //look for @media\n                tokenStream.mustMatch(Tokens.MEDIA_SYM);\n                line = tokenStream.token().startLine;\n                col = tokenStream.token().startCol;\n                \n                this._readWhitespace();               \n\n                mediaList = this._media_query_list();\n\n                tokenStream.mustMatch(Tokens.LBRACE);\n                this._readWhitespace();\n                \n                this.fire({\n                    type:   \"startmedia\",\n                    media:  mediaList,\n                    line:   line,\n                    col:    col\n                });\n                \n                while(true) {\n                    if (tokenStream.peek() == Tokens.PAGE_SYM){\n                        this._page();\n                    } else if (!this._ruleset()){\n                        break;\n                    }                \n                }\n                \n                tokenStream.mustMatch(Tokens.RBRACE);\n                this._readWhitespace();\n        \n                this.fire({\n                    type:   \"endmedia\",\n                    media:  mediaList,\n                    line:   line,\n                    col:    col\n                });\n            },                           \n        \n\n            //CSS3 Media Queries\n            _media_query_list: function(){\n                /*\n                 * media_query_list\n                 *   : S* [media_query [ ',' S* media_query ]* ]?\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    mediaList   = [];\n                \n                \n                this._readWhitespace();\n                \n                if (tokenStream.peek() == Tokens.IDENT || tokenStream.peek() == Tokens.LPAREN){\n                    mediaList.push(this._media_query());\n                }\n                \n                while(tokenStream.match(Tokens.COMMA)){\n                    this._readWhitespace();\n                    mediaList.push(this._media_query());\n                }\n                \n                return mediaList;\n            },\n            \n            /*\n             * Note: \"expression\" in the grammar maps to the _media_expression\n             * method.\n             \n             */\n            _media_query: function(){\n                /*\n                 * media_query\n                 *   : [ONLY | NOT]? S* media_type S* [ AND S* expression ]*\n                 *   | expression [ AND S* expression ]*\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    type        = null,\n                    ident       = null,\n                    token       = null,\n                    expressions = [];\n                    \n                if (tokenStream.match(Tokens.IDENT)){\n                    ident = tokenStream.token().value.toLowerCase();\n                    \n                    //since there's no custom tokens for these, need to manually check\n                    if (ident != \"only\" && ident != \"not\"){\n                        tokenStream.unget();\n                        ident = null;\n                    } else {\n                        token = tokenStream.token();\n                    }\n                }\n                                \n                this._readWhitespace();\n                \n                if (tokenStream.peek() == Tokens.IDENT){\n                    type = this._media_type();\n                    if (token === null){\n                        token = tokenStream.token();\n                    }\n                } else if (tokenStream.peek() == Tokens.LPAREN){\n                    if (token === null){\n                        token = tokenStream.LT(1);\n                    }\n                    expressions.push(this._media_expression());\n                }                               \n                \n                if (type === null && expressions.length === 0){\n                    return null;\n                } else {                \n                    this._readWhitespace();\n                    while (tokenStream.match(Tokens.IDENT)){\n                        if (tokenStream.token().value.toLowerCase() != \"and\"){\n                            this._unexpectedToken(tokenStream.token());\n                        }\n                        \n                        this._readWhitespace();\n                        expressions.push(this._media_expression());\n                    }\n                }\n\n                return new MediaQuery(ident, type, expressions, token.startLine, token.startCol);\n            },\n\n            //CSS3 Media Queries\n            _media_type: function(){\n                /*\n                 * media_type\n                 *   : IDENT\n                 *   ;\n                 */\n                return this._media_feature();           \n            },\n\n            /**\n             * Note: in CSS3 Media Queries, this is called \"expression\".\n             * Renamed here to avoid conflict with CSS3 Selectors\n             * definition of \"expression\". Also note that \"expr\" in the\n             * grammar now maps to \"expression\" from CSS3 selectors.\n             * @method _media_expression\n             * @private\n             */\n            _media_expression: function(){\n                /*\n                 * expression\n                 *  : '(' S* media_feature S* [ ':' S* expr ]? ')' S*\n                 *  ;\n                 */\n                var tokenStream = this._tokenStream,\n                    feature     = null,\n                    token,\n                    expression  = null;\n                \n                tokenStream.mustMatch(Tokens.LPAREN);\n                \n                feature = this._media_feature();\n                this._readWhitespace();\n                \n                if (tokenStream.match(Tokens.COLON)){\n                    this._readWhitespace();\n                    token = tokenStream.LT(1);\n                    expression = this._expression();\n                }\n                \n                tokenStream.mustMatch(Tokens.RPAREN);\n                this._readWhitespace();\n\n                return new MediaFeature(feature, (expression ? new SyntaxUnit(expression, token.startLine, token.startCol) : null));            \n            },\n\n            //CSS3 Media Queries\n            _media_feature: function(){\n                /*\n                 * media_feature\n                 *   : IDENT\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream;\n                    \n                tokenStream.mustMatch(Tokens.IDENT);\n                \n                return SyntaxUnit.fromToken(tokenStream.token());            \n            },\n            \n            //CSS3 Paged Media\n            _page: function(){\n                /*\n                 * page:\n                 *    PAGE_SYM S* IDENT? pseudo_page? S* \n                 *    '{' S* [ declaration | margin ]? [ ';' S* [ declaration | margin ]? ]* '}' S*\n                 *    ;\n                 */            \n                var tokenStream = this._tokenStream,\n                    line,\n                    col,\n                    identifier  = null,\n                    pseudoPage  = null;\n                \n                //look for @page\n                tokenStream.mustMatch(Tokens.PAGE_SYM);\n                line = tokenStream.token().startLine;\n                col = tokenStream.token().startCol;\n                \n                this._readWhitespace();\n                \n                if (tokenStream.match(Tokens.IDENT)){\n                    identifier = tokenStream.token().value;\n\n                    //The value 'auto' may not be used as a page name and MUST be treated as a syntax error.\n                    if (identifier.toLowerCase() === \"auto\"){\n                        this._unexpectedToken(tokenStream.token());\n                    }\n                }                \n                \n                //see if there's a colon upcoming\n                if (tokenStream.peek() == Tokens.COLON){\n                    pseudoPage = this._pseudo_page();\n                }\n            \n                this._readWhitespace();\n                \n                this.fire({\n                    type:   \"startpage\",\n                    id:     identifier,\n                    pseudo: pseudoPage,\n                    line:   line,\n                    col:    col\n                });                   \n\n                this._readDeclarations(true, true);                \n                \n                this.fire({\n                    type:   \"endpage\",\n                    id:     identifier,\n                    pseudo: pseudoPage,\n                    line:   line,\n                    col:    col\n                });             \n            \n            },\n            \n            //CSS3 Paged Media\n            _margin: function(){\n                /*\n                 * margin :\n                 *    margin_sym S* '{' declaration [ ';' S* declaration? ]* '}' S*\n                 *    ;\n                 */\n                var tokenStream = this._tokenStream,\n                    line,\n                    col,\n                    marginSym   = this._margin_sym();\n\n                if (marginSym){\n                    line = tokenStream.token().startLine;\n                    col = tokenStream.token().startCol;\n                \n                    this.fire({\n                        type: \"startpagemargin\",\n                        margin: marginSym,\n                        line:   line,\n                        col:    col\n                    });    \n                    \n                    this._readDeclarations(true);\n\n                    this.fire({\n                        type: \"endpagemargin\",\n                        margin: marginSym,\n                        line:   line,\n                        col:    col\n                    });    \n                    return true;\n                } else {\n                    return false;\n                }\n            },\n\n            //CSS3 Paged Media\n            _margin_sym: function(){\n            \n                /*\n                 * margin_sym :\n                 *    TOPLEFTCORNER_SYM | \n                 *    TOPLEFT_SYM | \n                 *    TOPCENTER_SYM | \n                 *    TOPRIGHT_SYM | \n                 *    TOPRIGHTCORNER_SYM |\n                 *    BOTTOMLEFTCORNER_SYM | \n                 *    BOTTOMLEFT_SYM | \n                 *    BOTTOMCENTER_SYM | \n                 *    BOTTOMRIGHT_SYM |\n                 *    BOTTOMRIGHTCORNER_SYM |\n                 *    LEFTTOP_SYM |\n                 *    LEFTMIDDLE_SYM |\n                 *    LEFTBOTTOM_SYM |\n                 *    RIGHTTOP_SYM |\n                 *    RIGHTMIDDLE_SYM |\n                 *    RIGHTBOTTOM_SYM \n                 *    ;\n                 */\n            \n                var tokenStream = this._tokenStream;\n            \n                if(tokenStream.match([Tokens.TOPLEFTCORNER_SYM, Tokens.TOPLEFT_SYM,\n                        Tokens.TOPCENTER_SYM, Tokens.TOPRIGHT_SYM, Tokens.TOPRIGHTCORNER_SYM,\n                        Tokens.BOTTOMLEFTCORNER_SYM, Tokens.BOTTOMLEFT_SYM, \n                        Tokens.BOTTOMCENTER_SYM, Tokens.BOTTOMRIGHT_SYM,\n                        Tokens.BOTTOMRIGHTCORNER_SYM, Tokens.LEFTTOP_SYM, \n                        Tokens.LEFTMIDDLE_SYM, Tokens.LEFTBOTTOM_SYM, Tokens.RIGHTTOP_SYM,\n                        Tokens.RIGHTMIDDLE_SYM, Tokens.RIGHTBOTTOM_SYM]))\n                {\n                    return SyntaxUnit.fromToken(tokenStream.token());                \n                } else {\n                    return null;\n                }\n            \n            },\n            \n            _pseudo_page: function(){\n                /*\n                 * pseudo_page\n                 *   : ':' IDENT\n                 *   ;    \n                 */\n        \n                var tokenStream = this._tokenStream;\n                \n                tokenStream.mustMatch(Tokens.COLON);\n                tokenStream.mustMatch(Tokens.IDENT);\n                \n                //TODO: CSS3 Paged Media says only \"left\", \"center\", and \"right\" are allowed\n                \n                return tokenStream.token().value;\n            },\n            \n            _font_face: function(){\n                /*\n                 * font_face\n                 *   : FONT_FACE_SYM S* \n                 *     '{' S* declaration [ ';' S* declaration ]* '}' S*\n                 *   ;\n                 */     \n                var tokenStream = this._tokenStream,\n                    line,\n                    col;\n                \n                //look for @page\n                tokenStream.mustMatch(Tokens.FONT_FACE_SYM);\n                line = tokenStream.token().startLine;\n                col = tokenStream.token().startCol;\n                \n                this._readWhitespace();\n\n                this.fire({\n                    type:   \"startfontface\",\n                    line:   line,\n                    col:    col\n                });                    \n                \n                this._readDeclarations(true);\n                \n                this.fire({\n                    type:   \"endfontface\",\n                    line:   line,\n                    col:    col\n                });              \n            },\n\n            _operator: function(){\n            \n                /*\n                 * operator\n                 *  : '/' S* | ',' S* | /( empty )/\n                 *  ;\n                 */    \n                 \n                var tokenStream = this._tokenStream,\n                    token       = null;\n                \n                if (tokenStream.match([Tokens.SLASH, Tokens.COMMA])){\n                    token =  tokenStream.token();\n                    this._readWhitespace();\n                } \n                return token ? PropertyValuePart.fromToken(token) : null;\n                \n            },\n            \n            _combinator: function(){\n            \n                /*\n                 * combinator\n                 *  : PLUS S* | GREATER S* | TILDE S* | S+\n                 *  ;\n                 */    \n                 \n                var tokenStream = this._tokenStream,\n                    value       = null,\n                    token;\n                \n                if(tokenStream.match([Tokens.PLUS, Tokens.GREATER, Tokens.TILDE])){                \n                    token = tokenStream.token();\n                    value = new Combinator(token.value, token.startLine, token.startCol);\n                    this._readWhitespace();\n                }\n                \n                return value;\n            },\n            \n            _unary_operator: function(){\n            \n                /*\n                 * unary_operator\n                 *  : '-' | '+'\n                 *  ;\n                 */\n                 \n                var tokenStream = this._tokenStream;\n                \n                if (tokenStream.match([Tokens.MINUS, Tokens.PLUS])){\n                    return tokenStream.token().value;\n                } else {\n                    return null;\n                }         \n            },\n            \n            _property: function(){\n            \n                /*\n                 * property\n                 *   : IDENT S*\n                 *   ;        \n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    value       = null,\n                    hack        = null,\n                    tokenValue,\n                    token,\n                    line,\n                    col;\n                    \n                //check for star hack - throws error if not allowed\n                if (tokenStream.peek() == Tokens.STAR && this.options.starHack){\n                    tokenStream.get();\n                    token = tokenStream.token();\n                    hack = token.value;\n                    line = token.startLine;\n                    col = token.startCol;\n                }\n                \n                if(tokenStream.match(Tokens.IDENT)){\n                    token = tokenStream.token();\n                    tokenValue = token.value;\n                    \n                    //check for underscore hack - no error if not allowed because it's valid CSS syntax\n                    if (tokenValue.charAt(0) == \"_\" && this.options.underscoreHack){\n                        hack = \"_\";\n                        tokenValue = tokenValue.substring(1);\n                    }\n                    \n                    value = new PropertyName(tokenValue, hack, (line||token.startLine), (col||token.startCol));\n                    this._readWhitespace();\n                }\n                \n                return value;\n            },\n        \n            //Augmented with CSS3 Selectors\n            _ruleset: function(){\n                /*\n                 * ruleset\n                 *   : selectors_group\n                 *     '{' S* declaration? [ ';' S* declaration? ]* '}' S*\n                 *   ;    \n                 */    \n                 \n                var tokenStream = this._tokenStream,\n                tt,\n                    selectors;\n\n\n                /*\n                 * Error Recovery: If even a single selector fails to parse,\n                 * then the entire ruleset should be thrown away.\n                 */\n                try {\n                    selectors = this._selectors_group();\n                } catch (ex){\n                    if (ex instanceof SyntaxError && !this.options.strict){\n                    \n                        //fire error event\n                        this.fire({\n                            type:       \"error\",\n                            error:      ex,\n                            message:    ex.message,\n                            line:       ex.line,\n                            col:        ex.col\n                        });                          \n                        \n                        //skip over everything until closing brace\n                        tt = tokenStream.advance([Tokens.RBRACE]);\n                        if (tt == Tokens.RBRACE){\n                            //if there's a right brace, the rule is finished so don't do anything\n                        } else {\n                            //otherwise, rethrow the error because it wasn't handled properly\n                            throw ex;\n                        }                        \n                        \n                    } else {\n                        //not a syntax error, rethrow it\n                        throw ex;\n                    }                \n                \n                    //trigger parser to continue\n                    return true;\n                }\n                \n                //if it got here, all selectors parsed\n                if (selectors){ \n                                    \n                    this.fire({\n                        type:       \"startrule\",\n                        selectors:  selectors,\n                        line:       selectors[0].line,\n                        col:        selectors[0].col\n                    });                \n                    \n                    this._readDeclarations(true);                \n                    \n                    this.fire({\n                        type:       \"endrule\",\n                        selectors:  selectors,\n                        line:       selectors[0].line,\n                        col:        selectors[0].col\n                    });  \n                    \n                }\n                \n                return selectors;\n                \n            },\n\n            //CSS3 Selectors\n            _selectors_group: function(){\n            \n                /*            \n                 * selectors_group\n                 *   : selector [ COMMA S* selector ]*\n                 *   ;\n                 */           \n                var tokenStream = this._tokenStream,\n                    selectors   = [],\n                    selector;\n                    \n                selector = this._selector();\n                if (selector !== null){\n                \n                    selectors.push(selector);\n                    while(tokenStream.match(Tokens.COMMA)){\n                        this._readWhitespace();\n                        selector = this._selector();\n                        if (selector !== null){\n                            selectors.push(selector);\n                        } else {\n                            this._unexpectedToken(tokenStream.LT(1));\n                        }\n                    }\n                }\n\n                return selectors.length ? selectors : null;\n            },\n                \n            //CSS3 Selectors\n            _selector: function(){\n                /*\n                 * selector\n                 *   : simple_selector_sequence [ combinator simple_selector_sequence ]*\n                 *   ;    \n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    selector    = [],\n                    nextSelector = null,\n                    combinator  = null,\n                    ws          = null;\n                \n                //if there's no simple selector, then there's no selector\n                nextSelector = this._simple_selector_sequence();\n                if (nextSelector === null){\n                    return null;\n                }\n                \n                selector.push(nextSelector);\n                \n                do {\n                    \n                    //look for a combinator\n                    combinator = this._combinator();\n                    \n                    if (combinator !== null){\n                        selector.push(combinator);\n                        nextSelector = this._simple_selector_sequence();\n                        \n                        //there must be a next selector\n                        if (nextSelector === null){\n                            this._unexpectedToken(this.LT(1));\n                        } else {\n                        \n                            //nextSelector is an instance of SelectorPart\n                            selector.push(nextSelector);\n                        }\n                    } else {\n                        \n                        //if there's not whitespace, we're done\n                        if (this._readWhitespace()){           \n        \n                            //add whitespace separator\n                            ws = new Combinator(tokenStream.token().value, tokenStream.token().startLine, tokenStream.token().startCol);\n                            \n                            //combinator is not required\n                            combinator = this._combinator();\n                            \n                            //selector is required if there's a combinator\n                            nextSelector = this._simple_selector_sequence();\n                            if (nextSelector === null){                        \n                                if (combinator !== null){\n                                    this._unexpectedToken(tokenStream.LT(1));\n                                }\n                            } else {\n                                \n                                if (combinator !== null){\n                                    selector.push(combinator);\n                                } else {\n                                    selector.push(ws);\n                                }\n                                \n                                selector.push(nextSelector);\n                            }     \n                        } else {\n                            break;\n                        }               \n                    \n                    }\n                } while(true);\n                \n                return new Selector(selector, selector[0].line, selector[0].col);\n            },\n            \n            //CSS3 Selectors\n            _simple_selector_sequence: function(){\n                /*\n                 * simple_selector_sequence\n                 *   : [ type_selector | universal ]\n                 *     [ HASH | class | attrib | pseudo | negation ]*\n                 *   | [ HASH | class | attrib | pseudo | negation ]+\n                 *   ;\n                 */\n                 \n                var tokenStream = this._tokenStream,\n                \n                    //parts of a simple selector\n                    elementName = null,\n                    modifiers   = [],\n                    \n                    //complete selector text\n                    selectorText= \"\",\n\n                    //the different parts after the element name to search for\n                    components  = [\n                        //HASH\n                        function(){\n                            return tokenStream.match(Tokens.HASH) ?\n                                    new SelectorSubPart(tokenStream.token().value, \"id\", tokenStream.token().startLine, tokenStream.token().startCol) :\n                                    null;\n                        },\n                        this._class,\n                        this._attrib,\n                        this._pseudo,\n                        this._negation\n                    ],\n                    i           = 0,\n                    len         = components.length,\n                    component   = null,\n                    found       = false,\n                    line,\n                    col;\n                    \n                    \n                //get starting line and column for the selector\n                line = tokenStream.LT(1).startLine;\n                col = tokenStream.LT(1).startCol;\n                                        \n                elementName = this._type_selector();\n                if (!elementName){\n                    elementName = this._universal();\n                }\n                \n                if (elementName !== null){\n                    selectorText += elementName;\n                }                \n                \n                while(true){\n\n                    //whitespace means we're done\n                    if (tokenStream.peek() === Tokens.S){\n                        break;\n                    }\n                \n                    //check for each component\n                    while(i < len && component === null){\n                        component = components[i++].call(this);\n                    }\n        \n                    if (component === null){\n                    \n                        //we don't have a selector\n                        if (selectorText === \"\"){\n                            return null;\n                        } else {\n                            break;\n                        }\n                    } else {\n                        i = 0;\n                        modifiers.push(component);\n                        selectorText += component.toString(); \n                        component = null;\n                    }\n                }\n\n                 \n                return selectorText !== \"\" ?\n                        new SelectorPart(elementName, modifiers, selectorText, line, col) :\n                        null;\n            },            \n            \n            //CSS3 Selectors\n            _type_selector: function(){\n                /*\n                 * type_selector\n                 *   : [ namespace_prefix ]? element_name\n                 *   ;\n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    ns          = this._namespace_prefix(),\n                    elementName = this._element_name();\n                    \n                if (!elementName){                    \n                    /*\n                     * Need to back out the namespace that was read due to both\n                     * type_selector and universal reading namespace_prefix\n                     * first. Kind of hacky, but only way I can figure out\n                     * right now how to not change the grammar.\n                     */\n                    if (ns){\n                        tokenStream.unget();\n                        if (ns.length > 1){\n                            tokenStream.unget();\n                        }\n                    }\n                \n                    return null;\n                } else {     \n                    if (ns){\n                        elementName.text = ns + elementName.text;\n                        elementName.col -= ns.length;\n                    }\n                    return elementName;\n                }\n            },\n            \n            //CSS3 Selectors\n            _class: function(){\n                /*\n                 * class\n                 *   : '.' IDENT\n                 *   ;\n                 */    \n                 \n                var tokenStream = this._tokenStream,\n                    token;\n                \n                if (tokenStream.match(Tokens.DOT)){\n                    tokenStream.mustMatch(Tokens.IDENT);    \n                    token = tokenStream.token();\n                    return new SelectorSubPart(\".\" + token.value, \"class\", token.startLine, token.startCol - 1);        \n                } else {\n                    return null;\n                }\n        \n            },\n            \n            //CSS3 Selectors\n            _element_name: function(){\n                /*\n                 * element_name\n                 *   : IDENT\n                 *   ;\n                 */    \n                \n                var tokenStream = this._tokenStream,\n                    token;\n                \n                if (tokenStream.match(Tokens.IDENT)){\n                    token = tokenStream.token();\n                    return new SelectorSubPart(token.value, \"elementName\", token.startLine, token.startCol);        \n                \n                } else {\n                    return null;\n                }\n            },\n            \n            //CSS3 Selectors\n            _namespace_prefix: function(){\n                /*            \n                 * namespace_prefix\n                 *   : [ IDENT | '*' ]? '|'\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    value       = \"\";\n                    \n                //verify that this is a namespace prefix\n                if (tokenStream.LA(1) === Tokens.PIPE || tokenStream.LA(2) === Tokens.PIPE){\n                        \n                    if(tokenStream.match([Tokens.IDENT, Tokens.STAR])){\n                        value += tokenStream.token().value;\n                    }\n                    \n                    tokenStream.mustMatch(Tokens.PIPE);\n                    value += \"|\";\n                    \n                }\n                \n                return value.length ? value : null;                \n            },\n            \n            //CSS3 Selectors\n            _universal: function(){\n                /*\n                 * universal\n                 *   : [ namespace_prefix ]? '*'\n                 *   ;            \n                 */\n                var tokenStream = this._tokenStream,\n                    value       = \"\",\n                    ns;\n                    \n                ns = this._namespace_prefix();\n                if(ns){\n                    value += ns;\n                }\n                \n                if(tokenStream.match(Tokens.STAR)){\n                    value += \"*\";\n                }\n                \n                return value.length ? value : null;\n                \n           },\n            \n            //CSS3 Selectors\n            _attrib: function(){\n                /*\n                 * attrib\n                 *   : '[' S* [ namespace_prefix ]? IDENT S*\n                 *         [ [ PREFIXMATCH |\n                 *             SUFFIXMATCH |\n                 *             SUBSTRINGMATCH |\n                 *             '=' |\n                 *             INCLUDES |\n                 *             DASHMATCH ] S* [ IDENT | STRING ] S*\n                 *         ]? ']'\n                 *   ;    \n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    value       = null,\n                    ns,\n                    token;\n                \n                if (tokenStream.match(Tokens.LBRACKET)){\n                    token = tokenStream.token();\n                    value = token.value;\n                    value += this._readWhitespace();\n                    \n                    ns = this._namespace_prefix();\n                    \n                    if (ns){\n                        value += ns;\n                    }\n                                        \n                    tokenStream.mustMatch(Tokens.IDENT);\n                    value += tokenStream.token().value;                    \n                    value += this._readWhitespace();\n                    \n                    if(tokenStream.match([Tokens.PREFIXMATCH, Tokens.SUFFIXMATCH, Tokens.SUBSTRINGMATCH,\n                            Tokens.EQUALS, Tokens.INCLUDES, Tokens.DASHMATCH])){\n                    \n                        value += tokenStream.token().value;                    \n                        value += this._readWhitespace();\n                        \n                        tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]);\n                        value += tokenStream.token().value;                    \n                        value += this._readWhitespace();\n                    }\n                    \n                    tokenStream.mustMatch(Tokens.RBRACKET);\n                                        \n                    return new SelectorSubPart(value + \"]\", \"attribute\", token.startLine, token.startCol);\n                } else {\n                    return null;\n                }\n            },\n            \n            //CSS3 Selectors\n            _pseudo: function(){\n            \n                /*\n                 * pseudo\n                 *   : ':' ':'? [ IDENT | functional_pseudo ]\n                 *   ;    \n                 */   \n            \n                var tokenStream = this._tokenStream,\n                    pseudo      = null,\n                    colons      = \":\",\n                    line,\n                    col;\n                \n                if (tokenStream.match(Tokens.COLON)){\n                \n                    if (tokenStream.match(Tokens.COLON)){\n                        colons += \":\";\n                    }\n                \n                    if (tokenStream.match(Tokens.IDENT)){\n                        pseudo = tokenStream.token().value;\n                        line = tokenStream.token().startLine;\n                        col = tokenStream.token().startCol - colons.length;\n                    } else if (tokenStream.peek() == Tokens.FUNCTION){\n                        line = tokenStream.LT(1).startLine;\n                        col = tokenStream.LT(1).startCol - colons.length;\n                        pseudo = this._functional_pseudo();\n                    }\n                    \n                    if (pseudo){\n                        pseudo = new SelectorSubPart(colons + pseudo, \"pseudo\", line, col);\n                    }\n                }\n        \n                return pseudo;\n            },\n            \n            //CSS3 Selectors\n            _functional_pseudo: function(){\n                /*\n                 * functional_pseudo\n                 *   : FUNCTION S* expression ')'\n                 *   ;\n                */            \n                \n                var tokenStream = this._tokenStream,\n                    value = null;\n                \n                if(tokenStream.match(Tokens.FUNCTION)){\n                    value = tokenStream.token().value;\n                    value += this._readWhitespace();\n                    value += this._expression();\n                    tokenStream.mustMatch(Tokens.RPAREN);\n                    value += \")\";\n                }\n                \n                return value;\n            },\n            \n            //CSS3 Selectors\n            _expression: function(){\n                /*\n                 * expression\n                 *   : [ [ PLUS | '-' | DIMENSION | NUMBER | STRING | IDENT ] S* ]+\n                 *   ;\n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    value       = \"\";\n                    \n                while(tokenStream.match([Tokens.PLUS, Tokens.MINUS, Tokens.DIMENSION,\n                        Tokens.NUMBER, Tokens.STRING, Tokens.IDENT, Tokens.LENGTH,\n                        Tokens.FREQ, Tokens.EMS, Tokens.EXS, Tokens.ANGLE, Tokens.TIME,\n                        Tokens.RESOLUTION])){\n                    \n                    value += tokenStream.token().value;\n                    value += this._readWhitespace();                        \n                }\n                \n                return value.length ? value : null;\n                \n            },\n\n            //CSS3 Selectors\n            _negation: function(){\n                /*            \n                 * negation\n                 *   : NOT S* negation_arg S* ')'\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    line,\n                    col,\n                    value       = \"\",\n                    arg,\n                    subpart     = null;\n                    \n                if (tokenStream.match(Tokens.NOT)){\n                    value = tokenStream.token().value;\n                    line = tokenStream.token().startLine;\n                    col = tokenStream.token().startCol;\n                    value += this._readWhitespace();\n                    arg = this._negation_arg();\n                    value += arg;\n                    value += this._readWhitespace();\n                    tokenStream.match(Tokens.RPAREN);\n                    value += tokenStream.token().value;\n                    \n                    subpart = new SelectorSubPart(value, \"not\", line, col);\n                    subpart.args.push(arg);\n                }\n                \n                return subpart;\n            },\n            \n            //CSS3 Selectors\n            _negation_arg: function(){            \n                /*\n                 * negation_arg\n                 *   : type_selector | universal | HASH | class | attrib | pseudo\n                 *   ;            \n                 */           \n                 \n                var tokenStream = this._tokenStream,\n                    args        = [\n                        this._type_selector,\n                        this._universal,\n                        function(){\n                            return tokenStream.match(Tokens.HASH) ?\n                                    new SelectorSubPart(tokenStream.token().value, \"id\", tokenStream.token().startLine, tokenStream.token().startCol) :\n                                    null;                        \n                        },\n                        this._class,\n                        this._attrib,\n                        this._pseudo                    \n                    ],\n                    arg         = null,\n                    i           = 0,\n                    len         = args.length,\n                    elementName,\n                    line,\n                    col,\n                    part;\n                    \n                line = tokenStream.LT(1).startLine;\n                col = tokenStream.LT(1).startCol;\n                \n                while(i < len && arg === null){\n                    \n                    arg = args[i].call(this);\n                    i++;\n                }\n                \n                //must be a negation arg\n                if (arg === null){\n                    this._unexpectedToken(tokenStream.LT(1));\n                }\n \n                //it's an element name\n                if (arg.type == \"elementName\"){\n                    part = new SelectorPart(arg, [], arg.toString(), line, col);\n                } else {\n                    part = new SelectorPart(null, [arg], arg.toString(), line, col);\n                }\n                \n                return part;                \n            },\n            \n            _declaration: function(){\n            \n                /*\n                 * declaration\n                 *   : property ':' S* expr prio?\n                 *   | /( empty )/\n                 *   ;     \n                 */    \n            \n                var tokenStream = this._tokenStream,\n                    property    = null,\n                    expr        = null,\n                    prio        = null;\n                \n                property = this._property();\n                if (property !== null){\n\n                    tokenStream.mustMatch(Tokens.COLON);\n                    this._readWhitespace();\n                    \n                    expr = this._expr();\n                    \n                    //if there's no parts for the value, it's an error\n                    if (!expr || expr.length === 0){\n                        this._unexpectedToken(tokenStream.LT(1));\n                    }\n                    \n                    prio = this._prio();\n                    \n                    this.fire({\n                        type:       \"property\",\n                        property:   property,\n                        value:      expr,\n                        important:  prio,\n                        line:       property.line,\n                        col:        property.col\n                    });                      \n                    \n                    return true;\n                } else {\n                    return false;\n                }\n            },\n            \n            _prio: function(){\n                /*\n                 * prio\n                 *   : IMPORTANT_SYM S*\n                 *   ;    \n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    result      = tokenStream.match(Tokens.IMPORTANT_SYM);\n                    \n                this._readWhitespace();\n                return result;\n            },\n            \n            _expr: function(){\n                /*\n                 * expr\n                 *   : term [ operator term ]*\n                 *   ;\n                 */\n        \n                var tokenStream = this._tokenStream,\n                    values      = [],\n\t\t\t\t\t//valueParts\t= [],\n                    value       = null,\n                    operator    = null;\n                    \n                value = this._term();\n                if (value !== null){\n                \n                    values.push(value);\n                    \n                    do {\n                        operator = this._operator();\n        \n                        //if there's an operator, keep building up the value parts\n                        if (operator){\n                            values.push(operator);\n                        } /*else {\n                            //if there's not an operator, you have a full value\n\t\t\t\t\t\t\tvalues.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col));\n\t\t\t\t\t\t\tvalueParts = [];\n\t\t\t\t\t\t}*/\n                        \n                        value = this._term();\n                        \n                        if (value === null){\n                            break;\n                        } else {\n                            values.push(value);\n                        }\n                    } while(true);\n                }\n\t\t\t\t\n\t\t\t\t//cleanup\n                /*if (valueParts.length){\n                    values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col));\n                }*/\n        \n                return values.length > 0 ? new PropertyValue(values, values[0].startLine, values[0].startCol) : null;\n            },\n            \n            _term: function(){                       \n            \n                /*\n                 * term\n                 *   : unary_operator?\n                 *     [ NUMBER S* | PERCENTAGE S* | LENGTH S* | EMS S* | EXS S* | ANGLE S* |\n                 *       TIME S* | FREQ S* | function | ie_function ]\n                 *   | STRING S* | IDENT S* | URI S* | UNICODERANGE S* | hexcolor\n                 *   ;\n                 */    \n        \n                var tokenStream = this._tokenStream,\n                    unary       = null,\n                    value       = null,\n                    line,\n                    col;\n                    \n                //returns the operator or null\n                unary = this._unary_operator();\n                if (unary !== null){\n                    line = tokenStream.token().startLine;\n                    col = tokenStream.token().startCol;\n                }                \n               \n                //exception for IE filters\n                if (tokenStream.peek() == Tokens.IE_FUNCTION && this.options.ieFilters){\n                \n                    value = this._ie_function();\n                    if (unary === null){\n                        line = tokenStream.token().startLine;\n                        col = tokenStream.token().startCol;\n                    }\n                \n                //see if there's a simple match\n                } else if (tokenStream.match([Tokens.NUMBER, Tokens.PERCENTAGE, Tokens.LENGTH,\n                        Tokens.EMS, Tokens.EXS, Tokens.ANGLE, Tokens.TIME,\n                        Tokens.FREQ, Tokens.STRING, Tokens.IDENT, Tokens.URI, Tokens.UNICODE_RANGE])){\n                 \n                    value = tokenStream.token().value;\n                    if (unary === null){\n                        line = tokenStream.token().startLine;\n                        col = tokenStream.token().startCol;\n                    }\n                    this._readWhitespace();\n                } else {\n                \n                    //see if it's a color\n                    value = this._hexcolor();\n                    if (value === null){\n                    \n                        //if there's no unary, get the start of the next token for line/col info\n                        if (unary === null){\n                            line = tokenStream.LT(1).startLine;\n                            col = tokenStream.LT(1).startCol;\n                        }                    \n                    \n                        //has to be a function\n                        if (value === null){\n                            \n                            /*\n                             * This checks for alpha(opacity=0) style of IE\n                             * functions. IE_FUNCTION only presents progid: style.\n                             */\n                            if (tokenStream.LA(3) == Tokens.EQUALS && this.options.ieFilters){\n                                value = this._ie_function();\n                            } else {\n                                value = this._function();\n                            }\n                        }\n\n                        /*if (value === null){\n                            return null;\n                            //throw new Error(\"Expected identifier at line \" + tokenStream.token().startLine + \", character \" +  tokenStream.token().startCol + \".\");\n                        }*/\n                    \n                    } else {\n                        if (unary === null){\n                            line = tokenStream.token().startLine;\n                            col = tokenStream.token().startCol;\n                        }                    \n                    }\n                \n                }                \n                \n                return value !== null ?\n                        new PropertyValuePart(unary !== null ? unary + value : value, line, col) :\n                        null;\n        \n            },\n            \n            _function: function(){\n            \n                /*\n                 * function\n                 *   : FUNCTION S* expr ')' S*\n                 *   ;\n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    functionText = null,\n                    expr        = null;\n                    \n                if (tokenStream.match(Tokens.FUNCTION)){\n                    functionText = tokenStream.token().value;\n                    this._readWhitespace();\n                    expr = this._expr();\n                    \n                    tokenStream.match(Tokens.RPAREN);    \n                    functionText += expr + \")\";\n                    this._readWhitespace();\n                }                \n                \n                return functionText;\n            }, \n            \n            _ie_function: function(){\n            \n                /* (My own extension)\n                 * ie_function\n                 *   : IE_FUNCTION S* IDENT '=' term [S* ','? IDENT '=' term]+ ')' S*\n                 *   ;\n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    functionText = null,\n                    expr        = null,\n                    lt;\n                    \n                //IE function can begin like a regular function, too\n                if (tokenStream.match([Tokens.IE_FUNCTION, Tokens.FUNCTION])){\n                    functionText = tokenStream.token().value;\n                    \n                    do {\n                    \n                        if (this._readWhitespace()){\n                            functionText += tokenStream.token().value;\n                        }\n                        \n                        //might be second time in the loop\n                        if (tokenStream.LA(0) == Tokens.COMMA){\n                            functionText += tokenStream.token().value;\n                        }\n                    \n                        tokenStream.match(Tokens.IDENT);\n                        functionText += tokenStream.token().value;\n                        \n                        tokenStream.match(Tokens.EQUALS);\n                        functionText += tokenStream.token().value;\n                        \n                        //functionText += this._term();\n                        lt = tokenStream.peek();\n                        while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){\n                            tokenStream.get();\n                            functionText += tokenStream.token().value;\n                            lt = tokenStream.peek();\n                        }\n                    } while(tokenStream.match([Tokens.COMMA, Tokens.S]));                    \n                    \n                    tokenStream.match(Tokens.RPAREN);    \n                    functionText += \")\";\n                    this._readWhitespace();\n                }                \n                \n                return functionText;\n            }, \n            \n            _hexcolor: function(){\n                /*\n                 * There is a constraint on the color that it must\n                 * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])\n                 * after the \"#\"; e.g., \"#000\" is OK, but \"#abcd\" is not.\n                 *\n                 * hexcolor\n                 *   : HASH S*\n                 *   ;\n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    token,\n                    color = null;\n                \n                if(tokenStream.match(Tokens.HASH)){\n                \n                    //need to do some validation here\n                    \n                    token = tokenStream.token();\n                    color = token.value;\n                    if (!/#[a-f0-9]{3,6}/i.test(color)){\n                        throw new SyntaxError(\"Expected a hex color but found '\" + color + \"' at line \" + token.startLine + \", character \" + token.startCol + \".\", token.startLine, token.startCol);\n                    }\n                    this._readWhitespace();\n                }\n                \n                return color;\n            },\n            \n            //-----------------------------------------------------------------\n            // Helper methods\n            //-----------------------------------------------------------------\n            \n            /**\n             * Not part of CSS grammar, but useful for skipping over\n             * combination of white space and HTML-style comments.\n             * @return {void}\n             * @method _skipCruft\n             * @private\n             */\n            _skipCruft: function(){\n                while(this._tokenStream.match([Tokens.S, Tokens.CDO, Tokens.CDC])){\n                    //noop\n                }\n            },\n\n            /**\n             * Not part of CSS grammar, but this pattern occurs frequently\n             * in the official CSS grammar. Split out here to eliminate\n             * duplicate code.\n             * @param {Boolean} checkStart Indicates if the rule should check\n             *      for the left brace at the beginning.\n             * @param {Boolean} readMargins Indicates if the rule should check\n             *      for margin patterns.\n             * @return {void}\n             * @method _readDeclarations\n             * @private\n             */\n            _readDeclarations: function(checkStart, readMargins){\n                /*\n                 * Reads the pattern\n                 * S* '{' S* declaration [ ';' S* declaration ]* '}' S*\n                 * or\n                 * S* '{' S* [ declaration | margin ]? [ ';' S* [ declaration | margin ]? ]* '}' S*\n                 * Note that this is how it is described in CSS3 Paged Media, but is actually incorrect.\n                 * A semicolon is only necessary following a delcaration is there's another declaration\n                 * or margin afterwards. \n                 */\n                var tokenStream = this._tokenStream,\n                    tt;\n                       \n\n                this._readWhitespace();\n                \n                if (checkStart){\n                    tokenStream.mustMatch(Tokens.LBRACE);            \n                }\n                \n                this._readWhitespace();\n\n                try {\n                    \n                    while(true){\n                    \n                        if (readMargins && this._margin()){\n                            //noop\n                        } else if (this._declaration()){\n                            if (!tokenStream.match(Tokens.SEMICOLON)){\n                                break;\n                            }\n                        } else {\n                            break;\n                        }\n                    \n                        //if ((!this._margin() && !this._declaration()) || !tokenStream.match(Tokens.SEMICOLON)){\n                        //    break;\n                        //}\n                        this._readWhitespace();\n                    }\n                    \n                    tokenStream.mustMatch(Tokens.RBRACE);\n                    this._readWhitespace();\n                    \n                } catch (ex) {\n                    if (ex instanceof SyntaxError && !this.options.strict){\n                    \n                        //fire error event\n                        this.fire({\n                            type:       \"error\",\n                            error:      ex,\n                            message:    ex.message,\n                            line:       ex.line,\n                            col:        ex.col\n                        });                          \n                        \n                        //see if there's another declaration\n                        tt = tokenStream.advance([Tokens.SEMICOLON, Tokens.RBRACE]);\n                        if (tt == Tokens.SEMICOLON){\n                            //if there's a semicolon, then there might be another declaration\n                            this._readDeclarations(false, readMargins);\n                        } else if (tt == Tokens.RBRACE){\n                            //if there's a right brace, the rule is finished so don't do anything\n                        } else {\n                            //otherwise, rethrow the error because it wasn't handled properly\n                            throw ex;\n                        }                        \n                        \n                    } else {\n                        //not a syntax error, rethrow it\n                        throw ex;\n                    }\n                }    \n            \n            },      \n            \n            /**\n             * In some cases, you can end up with two white space tokens in a\n             * row. Instead of making a change in every function that looks for\n             * white space, this function is used to match as much white space\n             * as necessary.\n             * @method _readWhitespace\n             * @return {String} The white space if found, empty string if not.\n             * @private\n             */\n            _readWhitespace: function(){\n            \n                var tokenStream = this._tokenStream,\n                    ws = \"\";\n                    \n                while(tokenStream.match(Tokens.S)){\n                    ws += tokenStream.token().value;\n                }\n                \n                return ws;\n            },\n          \n\n            /**\n             * Throws an error when an unexpected token is found.\n             * @param {Object} token The token that was found.\n             * @method _unexpectedToken\n             * @return {void}\n             * @private\n             */\n            _unexpectedToken: function(token){\n                throw new SyntaxError(\"Unexpected token '\" + token.value + \"' at line \" + token.startLine + \", char \" + token.startCol + \".\", token.startLine, token.startCol);\n            },\n            \n            /**\n             * Helper method used for parsing subparts of a style sheet.\n             * @return {void}\n             * @method _verifyEnd\n             * @private\n             */\n            _verifyEnd: function(){\n                if (this._tokenStream.LA(1) != Tokens.EOF){\n                    this._unexpectedToken(this._tokenStream.LT(1));\n                }            \n            },\n            \n            //-----------------------------------------------------------------\n            // Parsing methods\n            //-----------------------------------------------------------------\n            \n            parse: function(input){    \n                this._tokenStream = new TokenStream(input, Tokens);\n                this._stylesheet();\n            },\n            \n            parseStyleSheet: function(input){\n                //just passthrough\n                return this.parse(input);\n            },\n            \n            parseMediaQuery: function(input){\n                this._tokenStream = new TokenStream(input, Tokens);\n                var result = this._media_query();\n                \n                //if there's anything more, then it's an invalid selector\n                this._verifyEnd();\n                \n                //otherwise return result\n                return result;            \n            },\n            \n            /**\n             * Parses a property value (everything after the semicolon).\n             * @return {parserlib.css.PropertyValue} The property value.\n             * @throws parserlib.util.SyntaxError If an unexpected token is found.\n             * @method parserPropertyValue\n             */             \n            parsePropertyValue: function(input){\n            \n                this._tokenStream = new TokenStream(input, Tokens);\n                this._readWhitespace();\n                \n                var result = this._expr();\n                \n                //okay to have a trailing white space\n                this._readWhitespace();\n                \n                //if there's anything more, then it's an invalid selector\n                this._verifyEnd();\n                \n                //otherwise return result\n                return result;\n            },\n            \n            /**\n             * Parses a complete CSS rule, including selectors and\n             * properties.\n             * @param {String} input The text to parser.\n             * @return {Boolean} True if the parse completed successfully, false if not.\n             * @method parseRule\n             */\n            parseRule: function(input){\n                this._tokenStream = new TokenStream(input, Tokens);\n                \n                //skip any leading white space\n                this._readWhitespace();\n                \n                var result = this._ruleset();\n                \n                //skip any trailing white space\n                this._readWhitespace();\n\n                //if there's anything more, then it's an invalid selector\n                this._verifyEnd();\n                \n                //otherwise return result\n                return result;            \n            },\n            \n            /**\n             * Parses a single CSS selector (no comma)\n             * @param {String} input The text to parse as a CSS selector.\n             * @return {Selector} An object representing the selector.\n             * @throws parserlib.util.SyntaxError If an unexpected token is found.\n             * @method parseSelector\n             */\n            parseSelector: function(input){\n            \n                this._tokenStream = new TokenStream(input, Tokens);\n                \n                //skip any leading white space\n                this._readWhitespace();\n                \n                var result = this._selector();\n                \n                //skip any trailing white space\n                this._readWhitespace();\n\n                //if there's anything more, then it's an invalid selector\n                this._verifyEnd();\n                \n                //otherwise return result\n                return result;\n            }\n            \n        };\n        \n    //copy over onto prototype\n    for (prop in additions){\n        proto[prop] = additions[prop];\n    }   \n    \n    return proto;\n}();\n\n\n/*\nnth\n  : S* [ ['-'|'+']? INTEGER? {N} [ S* ['-'|'+'] S* INTEGER ]? |\n         ['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S*\n  ;\n*/\n/**\n * Represents a selector combinator (whitespace, +, >).\n * @namespace parserlib.css\n * @class PropertyName\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {String} text The text representation of the unit. \n * @param {String} hack The type of IE hack applied (\"*\", \"_\", or null).\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction PropertyName(text, hack, line, col){\n    \n    SyntaxUnit.call(this, (hack||\"\") + text, line, col);\n\n    /**\n     * The type of IE hack applied (\"*\", \"_\", or null).\n     * @type String\n     * @property hack\n     */\n    this.hack = hack;\n\n}\n\nPropertyName.prototype = new SyntaxUnit();\nPropertyName.prototype.constructor = PropertyName;\n\n/**\n * Represents a single part of a CSS property value, meaning that it represents\n * just everything single part between \":\" and \";\". If there are multiple values\n * separated by commas, this type represents just one of the values.\n * @param {String[]} parts An array of value parts making up this value.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n * @namespace parserlib.css\n * @class PropertyValue\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n */\nfunction PropertyValue(parts, line, col){\n\n    SyntaxUnit.call(this, parts.join(\" \"), line, col);\n    \n    /**\n     * The parts that make up the selector.\n     * @type Array\n     * @property parts\n     */\n    this.parts = parts;\n    \n}\n\nPropertyValue.prototype = new SyntaxUnit();\nPropertyValue.prototype.constructor = PropertyValue;\n\n/**\n * Represents a single part of a CSS property value, meaning that it represents\n * just one part of the data between \":\" and \";\".\n * @param {String} text The text representation of the unit.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n * @namespace parserlib.css\n * @class PropertyValuePart\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n */\nfunction PropertyValuePart(text, line, col){\n\n    SyntaxUnit.apply(this,arguments);\n    \n    /**\n     * Indicates the type of value unit.\n     * @type String\n     * @property type\n     */\n    this.type = \"unknown\";\n\n    //figure out what type of data it is\n    \n    var temp;\n    \n    //it is a measurement?\n    if (/^([+\\-]?[\\d\\.]+)([a-z]+)$/i.test(text)){  //dimension\n        this.type = \"dimension\";\n        this.value = +RegExp.$1;\n        this.units = RegExp.$2;\n        \n        //try to narrow down\n        switch(this.units.toLowerCase()){\n        \n            case \"em\":\n            case \"rem\":\n            case \"ex\":\n            case \"px\":\n            case \"cm\":\n            case \"mm\":\n            case \"in\":\n            case \"pt\":\n            case \"pc\":\n                this.type = \"length\";\n                break;\n                \n            case \"deg\":\n            case \"rad\":\n            case \"grad\":\n                this.type = \"angle\";\n                break;\n            \n            case \"ms\":\n            case \"s\":\n                this.type = \"time\";\n                break;\n            \n            case \"hz\":\n            case \"khz\":\n                this.type = \"frequency\";\n                break;\n            \n            case \"dpi\":\n            case \"dpcm\":\n                this.type = \"resolution\";\n                break;\n                \n            //default\n                \n        }\n        \n    } else if (/^([+\\-]?[\\d\\.]+)%$/i.test(text)){  //percentage\n        this.type = \"percentage\";\n        this.value = +RegExp.$1;\n    } else if (/^([+\\-]?[\\d\\.]+)%$/i.test(text)){  //percentage\n        this.type = \"percentage\";\n        this.value = +RegExp.$1;\n    } else if (/^([+\\-]?\\d+)$/i.test(text)){  //integer\n        this.type = \"integer\";\n        this.value = +RegExp.$1;\n    } else if (/^([+\\-]?[\\d\\.]+)$/i.test(text)){  //number\n        this.type = \"number\";\n        this.value = +RegExp.$1;\n    \n    } else if (/^#([a-f0-9]{3,6})/i.test(text)){  //hexcolor\n        this.type = \"color\";\n        temp = RegExp.$1;\n        if (temp.length == 3){\n            this.red    = parseInt(temp.charAt(0)+temp.charAt(0),16);\n            this.green  = parseInt(temp.charAt(1)+temp.charAt(1),16);\n            this.blue   = parseInt(temp.charAt(2)+temp.charAt(2),16);            \n        } else {\n            this.red    = parseInt(temp.substring(0,2),16);\n            this.green  = parseInt(temp.substring(2,4),16);\n            this.blue   = parseInt(temp.substring(4,6),16);            \n        }\n    } else if (/^rgb\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)/i.test(text)){ //rgb() color with absolute numbers\n        this.type   = \"color\";\n        this.red    = +RegExp.$1;\n        this.green  = +RegExp.$2;\n        this.blue   = +RegExp.$3;\n    } else if (/^rgb\\(\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*\\)/i.test(text)){ //rgb() color with percentages\n        this.type   = \"color\";\n        this.red    = +RegExp.$1 * 255 / 100;\n        this.green  = +RegExp.$2 * 255 / 100;\n        this.blue   = +RegExp.$3 * 255 / 100;\n    } else if (/^url\\([\"']?([^\\)\"']+)[\"']?\\)/i.test(text)){ //URI\n        this.type   = \"uri\";\n        this.uri    = RegExp.$1;\n    } else if (/^[\"'][^\"']*[\"']/.test(text)){    //string\n        this.type   = \"string\";\n        this.value  = eval(text);\n    } else if (Colors[text.toLowerCase()]){  //named color\n        this.type   = \"color\";\n        temp        = Colors[text.toLowerCase()].substring(1);\n        this.red    = parseInt(temp.substring(0,2),16);\n        this.green  = parseInt(temp.substring(2,4),16);\n        this.blue   = parseInt(temp.substring(4,6),16);         \n    } else if (/^[\\,\\/]$/.test(text)){\n        this.type   = \"operator\";\n        this.value  = text;\n    } else if (/^[a-z\\-\\u0080-\\uFFFF][a-z0-9\\-\\u0080-\\uFFFF]*$/i.test(text)){\n        this.type   = \"identifier\";\n        this.value  = text;\n    }\n\n}\n\nPropertyValuePart.prototype = new SyntaxUnit();\nPropertyValuePart.prototype.constructor = PropertyValue;\n\n/**\n * Create a new syntax unit based solely on the given token.\n * Convenience method for creating a new syntax unit when\n * it represents a single token instead of multiple.\n * @param {Object} token The token object to represent.\n * @return {parserlib.css.PropertyValuePart} The object representing the token.\n * @static\n * @method fromToken\n */\nPropertyValuePart.fromToken = function(token){\n    return new PropertyValuePart(token.value, token.startLine, token.startCol);\n};\n/**\n * Represents an entire single selector, including all parts but not\n * including multiple selectors (those separated by commas).\n * @namespace parserlib.css\n * @class Selector\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {Array} parts Array of selectors parts making up this selector.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction Selector(parts, line, col){\n    \n    SyntaxUnit.call(this, parts.join(\" \"), line, col);\n    \n    /**\n     * The parts that make up the selector.\n     * @type Array\n     * @property parts\n     */\n    this.parts = parts;\n\n}\n\nSelector.prototype = new SyntaxUnit();\nSelector.prototype.constructor = Selector;\n\n/**\n * Represents a single part of a selector string, meaning a single set of\n * element name and modifiers. This does not include combinators such as\n * spaces, +, >, etc.\n * @namespace parserlib.css\n * @class SelectorPart\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {String} elementName The element name in the selector or null\n *      if there is no element name.\n * @param {Array} modifiers Array of individual modifiers for the element.\n *      May be empty if there are none.\n * @param {String} text The text representation of the unit. \n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction SelectorPart(elementName, modifiers, text, line, col){\n    \n    SyntaxUnit.call(this, text, line, col);\n\n    /**\n     * The tag name of the element to which this part\n     * of the selector affects.\n     * @type String\n     * @property elementName\n     */\n    this.elementName = elementName;\n    \n    /**\n     * The parts that come after the element name, such as class names, IDs,\n     * pseudo classes/elements, etc.\n     * @type Array\n     * @property modifiers\n     */\n    this.modifiers = modifiers;\n\n}\n\nSelectorPart.prototype = new SyntaxUnit();\nSelectorPart.prototype.constructor = SelectorPart;\n\n/**\n * Represents a selector modifier string, meaning a class name, element name,\n * element ID, pseudo rule, etc.\n * @namespace parserlib.css\n * @class SelectorSubPart\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {String} text The text representation of the unit. \n * @param {String} type The type of selector modifier.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction SelectorSubPart(text, type, line, col){\n    \n    SyntaxUnit.call(this, text, line, col);\n\n    /**\n     * The type of modifier.\n     * @type String\n     * @property type\n     */\n    this.type = type;\n    \n    /**\n     * Some subparts have arguments, this represents them.\n     * @type Array\n     * @property args\n     */\n    this.args = [];\n\n}\n\nSelectorSubPart.prototype = new SyntaxUnit();\nSelectorSubPart.prototype.constructor = SelectorSubPart;\n\n\n \nvar h = /^[0-9a-fA-F]$/,\n    nonascii = /^[\\u0080-\\uFFFF]$/,\n    nl = /\\n|\\r\\n|\\r|\\f/;\n\n//-----------------------------------------------------------------------------\n// Helper functions\n//-----------------------------------------------------------------------------\n    \n \nfunction isHexDigit(c){\n    return c != null && h.test(c);\n}\n\nfunction isDigit(c){\n    return c != null && /\\d/.test(c);\n}\n\nfunction isWhitespace(c){\n    return c != null && /\\s/.test(c);\n}\n\nfunction isNewLine(c){\n    return c != null && nl.test(c);\n}\n\nfunction isNameStart(c){\n    return c != null && (/[a-z_\\u0080-\\uFFFF\\\\]/i.test(c));\n}\n\nfunction isNameChar(c){\n    return c != null && (isNameStart(c) || /[0-9\\-]/.test(c));\n}\n\nfunction isIdentStart(c){\n    return c != null && (isNameStart(c) || c == \"-\");\n}\n\nfunction mix(receiver, supplier){\n\tfor (var prop in supplier){\n\t\tif (supplier.hasOwnProperty(prop)){\n\t\t\treceiver[prop] = supplier[prop];\n\t\t}\n\t}\n\treturn receiver;\n}\n\n//-----------------------------------------------------------------------------\n// CSS Token Stream\n//-----------------------------------------------------------------------------\n\n\n/**\n * A token stream that produces CSS tokens.\n * @param {String|Reader} input The source of text to tokenize.\n * @constructor\n * @class TokenStream\n * @namespace parserlib.css\n */\nfunction TokenStream(input){\n\tTokenStreamBase.call(this, input, Tokens);\n}\n\nTokenStream.prototype = mix(new TokenStreamBase(), {\n\n    /**\n     * Overrides the TokenStreamBase method of the same name\n     * to produce CSS tokens.\n     * @param {variant} channel The name of the channel to use\n     *      for the next token.\n     * @return {Object} A token object representing the next token.\n     * @method _getToken\n     * @private\n     */\n    _getToken: function(channel){\n    \n        var c,\n            reader = this._reader,\n            token   = null,\n            startLine   = reader.getLine(),\n            startCol    = reader.getCol();\n        \n        c = reader.read();\n        \n\n        while(c){\n            switch(c){\n            \n                /*\n                 * Potential tokens:\n                 * - COMMENT\n                 * - SLASH\n                 * - CHAR\n                 */\n                case \"/\":\n\n                    if(reader.peek() == \"*\"){\n                        token = this.commentToken(c, startLine, startCol);\n                    } else {\n                        token = this.charToken(c, startLine, startCol);\n                    }\n                    break;                    \n                \n                /*\n                 * Potential tokens:\n                 * - DASHMATCH\n                 * - INCLUDES\n                 * - PREFIXMATCH\n                 * - SUFFIXMATCH\n                 * - SUBSTRINGMATCH\n                 * - CHAR\n                 */\n                case \"|\":\n                case \"~\":\n                case \"^\":\n                case \"$\":\n                case \"*\":\n                    if(reader.peek() == \"=\"){\n                        token = this.comparisonToken(c, startLine, startCol);\n                    } else {\n                        token = this.charToken(c, startLine, startCol);\n                    }\n                    break;                    \n                \n                /*\n                 * Potential tokens:\n                 * - STRING\n                 * - INVALID\n                 */\n                case \"\\\"\":\n                case \"'\":\n                    token = this.stringToken(c, startLine, startCol);                \n                    break;\n                    \n                /*\n                 * Potential tokens:\n                 * - HASH\n                 * - CHAR\n                 */\n                case \"#\":\n                    if (isNameChar(reader.peek())){\n                        token = this.hashToken(c, startLine, startCol);                        \n                    } else {\n                        token = this.charToken(c, startLine, startCol);\n                    }                \n                    break;\n                    \n                /*\n                 * Potential tokens:\n                 * - DOT\n                 * - NUMBER\n                 * - DIMENSION\n                 * - PERCENTAGE\n                 */\n                case \".\":\n                    if (isDigit(reader.peek())){\n                        token = this.numberToken(c, startLine, startCol);                        \n                    } else {\n                        token = this.charToken(c, startLine, startCol);\n                    }\n                    break;                    \n                    \n                /*\n                 * Potential tokens:\n                 * - CDC\n                 * - MINUS\n                 * - NUMBER\n                 * - DIMENSION\n                 * - PERCENTAGE\n                 */\n                case \"-\":\n                    if (reader.peek() == \"-\"){  //could be closing HTML-style comment\n                        token = this.htmlCommentEndToken(c, startLine, startCol);\n                    } else if (isNameStart(reader.peek())){\n                        token = this.identOrFunctionToken(c, startLine, startCol);\n                    } else {\n                        token = this.charToken(c, startLine, startCol);\n                    }\n                    break;\n                \n                /*\n                 * Potential tokens:\n                 * - IMPORTANT_SYM\n                 * - CHAR\n                 */\n                case \"!\":\n                    token = this.importantToken(c, startLine, startCol);\n                    break;\n                    \n                /*\n                 * Any at-keyword or CHAR\n                 */\n                case \"@\":\n                    token = this.atRuleToken(c, startLine, startCol);\n                    break;\n                    \n                /*\n                 * Potential tokens:\n                 * - NOT\n                 * - CHAR\n                 */\n                case \":\":\n                    token = this.notToken(c, startLine, startCol);\n                    break;         \n           \n                /*\n                 * Potential tokens:\n                 * - CDO\n                 * - CHAR\n                 */\n                case \"<\":\n                    token = this.htmlCommentStartToken(c, startLine, startCol);\n                    break;     \n\n                /*\n                 * Potential tokens:\n                 * - UNICODE_RANGE\n                 * - URL\n                 * - CHAR\n                 */\n                case \"U\":\n                case \"u\":\n                    if (reader.peek() == \"+\"){\n                        token = this.unicodeRangeToken(c, startLine, startCol);\n                        break;\n                    } \n                    /*falls through*/\n                    \n                default:\n                    \n                    /*\n                     * Potential tokens:\n                     * - NUMBER\n                     * - DIMENSION\n                     * - LENGTH\n                     * - FREQ\n                     * - TIME\n                     * - EMS\n                     * - EXS\n                     * - ANGLE\n                     */\n                    if (isDigit(c)){\n                        token = this.numberToken(c, startLine, startCol);\n                    } else \n                \n                    /*\n                     * Potential tokens:\n                     * - S\n                     */\n                    if (isWhitespace(c)){\n                        token = this.whitespaceToken(c, startLine, startCol);\n                    } else \n                    \n                    /*\n                     * Potential tokens:\n                     * - IDENT\n                     */                    \n                    if (isIdentStart(c)){\n                        token = this.identOrFunctionToken(c, startLine, startCol);\n                    } else \n                    \n                    /*\n                     * Potential tokens:\n                     * - CHAR\n                     * - PLUS\n                     */\n                    {\n                        token = this.charToken(c, startLine, startCol);                    \n                    }\n        \n        \n        \n        \n        \n        \n            }\n            \n            //make sure this token is wanted\n            //TODO: check channel\n            break;\n            \n            c = reader.read();\n        }\n        \n        if (!token && c == null){\n            token = this.createToken(Tokens.EOF,null,startLine,startCol);\n        }\n        \n        return token;\n    },\n    \n    //-------------------------------------------------------------------------\n    // Methods to create tokens\n    //-------------------------------------------------------------------------\n    \n    /**\n     * Produces a token based on available data and the current\n     * reader position information. This method is called by other\n     * private methods to create tokens and is never called directly.\n     * @param {int} tt The token type.\n     * @param {String} value The text value of the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @param {Object} options (Optional) Specifies a channel property\n     *      to indicate that a different channel should be scanned\n     *      and/or a hide property indicating that the token should\n     *      be hidden.\n     * @return {Object} A token object.\n     * @method createToken\n     */    \n    createToken: function(tt, value, startLine, startCol, options){\n        var reader = this._reader;\n        options = options || {};\n        \n        return {\n            value:      value,\n            type:       tt,\n            channel:    options.channel,\n            hide:       options.hide || false,\n            startLine:  startLine,\n            startCol:   startCol,\n            endLine:    reader.getLine(),\n            endCol:     reader.getCol()            \n        };    \n    }, \n    \n    //-------------------------------------------------------------------------\n    // Methods to create specific tokens\n    //-------------------------------------------------------------------------    \n    \n    /**\n     * Produces a token for any at-rule. If the at-rule is unknown, then\n     * the token is for a single \"@\" character.\n     * @param {String} first The first character for the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method atRuleToken\n     */    \n    atRuleToken: function(first, startLine, startCol){\n        var rule    = first,\n            reader  = this._reader,\n            tt      = Tokens.CHAR,\n            valid   = false,\n            ident,\n            c;            \n                    \n        /*\n         * First, mark where we are. There are only four @ rules,\n         * so anything else is really just an invalid token.\n         * Basically, if this doesn't match one of the known @\n         * rules, just return '@' as an unknown token and allow\n         * parsing to continue after that point.\n         */\n        reader.mark();\n        \n        //try to find the at-keyword        \n        ident = this.readName();\n        rule = first + ident;\n        tt = Tokens.type(rule.toLowerCase());\n        \n        //if it's not valid, use the first character only and reset the reader\n        if (tt == Tokens.CHAR || tt == Tokens.UNKNOWN){\n            tt = Tokens.CHAR;\n            rule = first;\n            reader.reset();\n        }            \n            \n        return this.createToken(tt, rule, startLine, startCol);        \n    },         \n    \n    /**\n     * Produces a character token based on the given character\n     * and location in the stream. If there's a special (non-standard)\n     * token name, this is used; otherwise CHAR is used.\n     * @param {String} c The character for the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method charToken\n     */\n    charToken: function(c, startLine, startCol){\n        var tt = Tokens.type(c);\n\n        if (tt == -1){\n            tt = Tokens.CHAR;\n        }\n        \n        return this.createToken(tt, c, startLine, startCol);\n    },    \n    \n    /**\n     * Produces a character token based on the given character\n     * and location in the stream. If there's a special (non-standard)\n     * token name, this is used; otherwise CHAR is used.\n     * @param {String} first The first character for the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method commentToken\n     */    \n    commentToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            comment = this.readComment(first);\n\n        return this.createToken(Tokens.COMMENT, comment, startLine, startCol);    \n    },    \n    \n    /**\n     * Produces a comparison token based on the given character\n     * and location in the stream. The next character must be\n     * read and is already known to be an equals sign.\n     * @param {String} c The character for the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method comparisonToken\n     */\n    comparisonToken: function(c, startLine, startCol){\n        var reader  = this._reader,\n            comparison  = c + reader.read(),\n            tt      = Tokens.type(comparison) || Tokens.CHAR;\n            \n        return this.createToken(tt, comparison, startLine, startCol);\n    },\n    \n    /**\n     * Produces a hash token based on the specified information. The\n     * first character provided is the pound sign (#) and then this\n     * method reads a name afterward.\n     * @param {String} first The first character (#) in the hash name.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method hashToken\n     */\n    hashToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            name    = this.readName(first);\n\n        return this.createToken(Tokens.HASH, name, startLine, startCol);    \n    },\n    \n    /**\n     * Produces a CDO or CHAR token based on the specified information. The\n     * first character is provided and the rest is read by the function to determine\n     * the correct token to create.\n     * @param {String} first The first character in the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method htmlCommentStartToken\n     */      \n    htmlCommentStartToken: function(first, startLine, startCol){\n        var reader      = this._reader,\n            text        = first;\n\n        reader.mark();        \n        text += reader.readCount(3);\n            \n        if (text == \"<!--\"){\n            return this.createToken(Tokens.CDO, text, startLine, startCol);\n        } else {\n            reader.reset();\n            return this.charToken(first, startLine, startCol);\n        }        \n    },    \n    \n    /**\n     * Produces a CDC or CHAR token based on the specified information. The\n     * first character is provided and the rest is read by the function to determine\n     * the correct token to create.\n     * @param {String} first The first character in the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method htmlCommentEndToken\n     */      \n    htmlCommentEndToken: function(first, startLine, startCol){\n        var reader      = this._reader,\n            text        = first;\n\n        reader.mark();        \n        text += reader.readCount(2);\n            \n        if (text == \"-->\"){\n            return this.createToken(Tokens.CDC, text, startLine, startCol);\n        } else {\n            reader.reset();\n            return this.charToken(first, startLine, startCol);\n        }        \n    },    \n    \n    /**\n     * Produces an IDENT or FUNCTION token based on the specified information. The\n     * first character is provided and the rest is read by the function to determine\n     * the correct token to create.\n     * @param {String} first The first character in the identifier.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method identOrFunctionToken\n     */    \n    identOrFunctionToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            ident   = this.readName(first),\n            tt      = Tokens.IDENT;\n\n        //if there's a left paren immediately after, it's a URI or function\n        if (reader.peek() == \"(\"){\n            ident += reader.read();\n            if (ident.toLowerCase() == \"url(\"){\n                tt = Tokens.URI;\n                ident = this.readURI(ident);\n                \n                //didn't find a valid URL or there's no closing paren\n                if (ident.toLowerCase() == \"url(\"){\n                    tt = Tokens.FUNCTION;\n                }\n            } else {\n                tt = Tokens.FUNCTION;\n            }\n        } else if (reader.peek() == \":\"){  //might be an IE function\n            \n            //IE-specific functions always being with progid:\n            if (ident.toLowerCase() == \"progid\"){\n                ident += reader.readTo(\"(\");\n                tt = Tokens.IE_FUNCTION;\n            }\n        }\n\n        return this.createToken(tt, ident, startLine, startCol);    \n    },\n    \n    /**\n     * Produces an IMPORTANT_SYM or CHAR token based on the specified information. The\n     * first character is provided and the rest is read by the function to determine\n     * the correct token to create.\n     * @param {String} first The first character in the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method importantToken\n     */      \n    importantToken: function(first, startLine, startCol){\n        var reader      = this._reader,\n            important   = first,\n            tt          = Tokens.CHAR,\n            temp,\n            c;\n\n        reader.mark();\n        c = reader.read();\n            \n        while(c){\n        \n            //there can be a comment in here\n            if (c == \"/\"){\n            \n                //if the next character isn't a star, then this isn't a valid !important token\n                if (reader.peek() != \"*\"){\n                    break;\n                } else {\n                    temp = this.readComment(c);\n                    if (temp == \"\"){    //broken!\n                        break;\n                    }\n                }\n            } else if (isWhitespace(c)){\n                important += c + this.readWhitespace();\n            } else if (/i/i.test(c)){\n                temp = reader.readCount(8);\n                if (/mportant/i.test(temp)){\n                    important += c + temp;\n                    tt = Tokens.IMPORTANT_SYM;\n                    \n                }\n                break;  //we're done\n            } else {\n                break;\n            }\n        \n            c = reader.read();\n        }\n        \n        if (tt == Tokens.CHAR){\n            reader.reset();\n            return this.charToken(first, startLine, startCol);\n        } else {\n            return this.createToken(tt, important, startLine, startCol);\n        }\n        \n        \n    },\n\n    /**\n     * Produces a NOT or CHAR token based on the specified information. The\n     * first character is provided and the rest is read by the function to determine\n     * the correct token to create.\n     * @param {String} first The first character in the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method notToken\n     */      \n    notToken: function(first, startLine, startCol){\n        var reader      = this._reader,\n            text        = first;\n\n        reader.mark();        \n        text += reader.readCount(4);\n            \n        if (text.toLowerCase() == \":not(\"){\n            return this.createToken(Tokens.NOT, text, startLine, startCol);\n        } else {\n            reader.reset();\n            return this.charToken(first, startLine, startCol);\n        }\n    },\n\n    /**\n     * Produces a number token based on the given character\n     * and location in the stream. This may return a token of\n     * NUMBER, EMS, EXS, LENGTH, ANGLE, TIME, FREQ, DIMENSION,\n     * or PERCENTAGE.\n     * @param {String} first The first character for the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method numberToken\n     */    \n    numberToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            value   = this.readNumber(first),\n            ident,\n            tt      = Tokens.NUMBER,\n            c       = reader.peek();\n            \n        if (isIdentStart(c)){\n            ident = this.readName(reader.read());\n            value += ident;            \n\n            if (/em|ex|px|gd|rem|vw|vh|vm|ch|cm|mm|in|pt|pc/i.test(ident)){\n                tt = Tokens.LENGTH;\n            } else if (/deg|rad|grad/i.test(ident)){\n                tt = Tokens.ANGLE;\n            } else if (/ms|s/i.test(ident)){\n                tt = Tokens.TIME;\n            } else if (/hz|khz/i.test(ident)){\n                tt = Tokens.FREQ;\n            } else if (/dpi|dpcm/i.test(ident)){\n                tt = Tokens.RESOLUTION;\n            } else {\n                tt = Tokens.DIMENSION;\n            }\n\n        } else if (c == \"%\"){\n            value += reader.read();\n            tt = Tokens.PERCENTAGE;\n        }\n            \n        return this.createToken(tt, value, startLine, startCol);            \n    },    \n    \n    /**\n     * Produces a string token based on the given character\n     * and location in the stream. Since strings may be indicated\n     * by single or double quotes, a failure to match starting\n     * and ending quotes results in an INVALID token being generated.\n     * The first character in the string is passed in and then\n     * the rest are read up to and including the final quotation mark.\n     * @param {String} first The first character in the string.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method stringToken\n     */    \n    stringToken: function(first, startLine, startCol){\n        var delim   = first,\n            string  = first,\n            reader  = this._reader,\n            prev    = first,\n            tt      = Tokens.STRING,\n            c       = reader.read();\n            \n        while(c){\n            string += c;\n            \n            //if the delimiter is found with an escapement, we're done.\n            if (c == delim && prev != \"\\\\\"){\n                break;\n            }\n\n            //if there's a newline without an escapement, it's an invalid string\n            if (isNewLine(reader.peek()) && c != \"\\\\\"){\n                tt = Tokens.INVALID;\n                break;\n            }\n        \n            //save previous and get next\n            prev = c;\n            c = reader.read();\n        }\n        \n        //if c is null, that means we're out of input and the string was never closed\n        if (c == null){\n            tt = Tokens.INVALID;\n        }\n            \n        return this.createToken(tt, string, startLine, startCol);        \n    },    \n    \n    unicodeRangeToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            value   = first,\n            temp,\n            tt      = Tokens.CHAR;\n         \n        //then it should be a unicode range\n        if (reader.peek() == \"+\"){\n            reader.mark();\n            value += reader.read();\n            value += this.readUnicodeRangePart(true);\n            \n            //ensure there's an actual unicode range here\n            if (value.length == 2){\n                reader.reset();\n            } else {\n                \n                tt = Tokens.UNICODE_RANGE;\n            \n                //if there's a ? in the first part, there can't be a second part\n                if (value.indexOf(\"?\") == -1){\n                            \n                    if (reader.peek() == \"-\"){\n                        reader.mark();\n                        temp = reader.read();\n                        temp += this.readUnicodeRangePart(false);\n                        \n                        //if there's not another value, back up and just take the first\n                        if (temp.length == 1){\n                            reader.reset();\n                        } else {\n                            value += temp;\n                        }\n                    }\n\n                }\n            }\n        }\n    \n        return this.createToken(tt, value, startLine, startCol);\n    },\n    \n    /**\n     * Produces a S token based on the specified information. Since whitespace\n     * may have multiple characters, this consumes all whitespace characters\n     * into a single token.\n     * @param {String} first The first character in the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method whitespaceToken\n     */          \n    whitespaceToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            value   = first + this.readWhitespace();\n        return this.createToken(Tokens.S, value, startLine, startCol);            \n    },    \n   \n\n\n\n    //-------------------------------------------------------------------------\n    // Methods to read values from the string stream\n    //-------------------------------------------------------------------------\n    \n    readUnicodeRangePart: function(allowQuestionMark){\n        var reader  = this._reader,\n            part = \"\",            \n            c       = reader.peek();\n        \n        //first read hex digits\n        while(isHexDigit(c) && part.length < 6){\n            reader.read();\n            part += c;\n            c = reader.peek();            \n        }\n        \n        //then read question marks if allowed\n        if (allowQuestionMark){\n            while(c == \"?\" && part.length < 6){\n                reader.read();\n                part += c;\n                c = reader.peek();            \n            }\n        }\n\n        //there can't be any other characters after this point\n        \n        return part;    \n    },\n    \n    readWhitespace: function(){\n        var reader  = this._reader,\n            whitespace = \"\",\n            c       = reader.peek();\n        \n        while(isWhitespace(c)){\n            reader.read();\n            whitespace += c;\n            c = reader.peek();            \n        }\n        \n        return whitespace;\n    },\n    readNumber: function(first){\n        var reader  = this._reader,\n            number  = first,\n            hasDot  = (first == \".\"),\n            c       = reader.peek();\n        \n\n        while(c){\n            if (isDigit(c)){\n                number += reader.read();\n            } else if (c == \".\"){\n                if (hasDot){\n                    break;\n                } else {\n                    hasDot = true;\n                    number += reader.read();\n                }\n            } else {\n                break;\n            }\n            \n            c = reader.peek();\n        }        \n        \n        return number;\n    },\n    readString: function(){\n        var reader  = this._reader,\n            delim   = reader.read(),\n            string  = delim,            \n            prev    = delim,\n            c       = reader.peek();\n            \n        while(c){\n            c = reader.read();\n            string += c;\n            \n            //if the delimiter is found with an escapement, we're done.\n            if (c == delim && prev != \"\\\\\"){\n                break;\n            }\n\n            //if there's a newline without an escapement, it's an invalid string\n            if (isNewLine(reader.peek()) && c != \"\\\\\"){\n                string = \"\";\n                break;\n            }\n        \n            //save previous and get next\n            prev = c;\n            c = reader.peek();\n        }\n        \n        //if c is null, that means we're out of input and the string was never closed\n        if (c == null){\n            string = \"\";\n        }\n                \n        return string;\n    },\n    readURI: function(first){\n        var reader  = this._reader,\n            uri     = first,\n            inner   = \"\",\n            c       = reader.peek();\n            \n        reader.mark();\n        \n        //skip whitespace before\n        while(c && isWhitespace(c)){\n            reader.read();\n            c = reader.peek();\n        }\n            \n        //it's a string\n        if (c == \"'\" || c == \"\\\"\"){\n            inner = this.readString();\n        } else {\n            inner = this.readURL();\n        }\n        \n        c = reader.peek();\n\n        //skip whitespace after\n        while(c && isWhitespace(c)){\n            reader.read();\n            c = reader.peek();\n        }\n            \n        //if there was no inner value or the next character isn't closing paren, it's not a URI\n        if (inner == \"\" || c != \")\"){\n            uri = first;\n            reader.reset();\n        } else {\n            uri += inner + reader.read();\n        }\n                \n        return uri;\n    },\n    readURL: function(){\n        var reader  = this._reader,\n            url     = \"\",\n            c       = reader.peek();\n    \n        //TODO: Check for escape and nonascii\n        while (/^[!#$%&\\\\*-~]$/.test(c)){\n            url += reader.read();\n            c = reader.peek();\n        }\n    \n        return url;\n    \n    },\n    readName: function(first){\n        var reader  = this._reader,\n            ident   = first || \"\",\n            c       = reader.peek();\n        \n\n        while(c && isNameChar(c)){\n            ident += reader.read();\n            c = reader.peek();\n        }\n        \n        return ident;\n    },    \n    readComment: function(first){\n        var reader  = this._reader,\n            comment = first || \"\",\n            c       = reader.read();\n        \n        if (c == \"*\"){\n            while(c){\n                comment += c;\n                \n                //look for end of comment\n                if (c == \"*\" && reader.peek() == \"/\"){\n                    comment += reader.read();\n                    break;\n                }\n                \n                c = reader.read();\n            }\n            \n            return comment;\n        } else {\n            return \"\";\n        }\n    \n    },\n    \n\n\n\n});\n\nvar Tokens  = [\n\n    /*\n     * The following token names are defined in CSS3 Grammar: http://www.w3.org/TR/css3-syntax/#lexical\n     */\n     \n    //HTML-style comments\n    { name: \"CDO\"},\n    { name: \"CDC\"},\n\n    //ignorables\n    { name: \"S\", whitespace: true/*, channel: \"ws\"*/},\n    { name: \"COMMENT\", comment: true, hide: true, channel: \"comment\" },\n        \n    //attribute equality\n    { name: \"INCLUDES\", text: \"~=\"},\n    { name: \"DASHMATCH\", text: \"|=\"},\n    { name: \"PREFIXMATCH\", text: \"^=\"},\n    { name: \"SUFFIXMATCH\", text: \"$=\"},\n    { name: \"SUBSTRINGMATCH\", text: \"*=\"},\n        \n    //identifier types\n    { name: \"STRING\"},     \n    { name: \"IDENT\"},\n    { name: \"HASH\"},\n\n    //at-keywords\n    { name: \"IMPORT_SYM\", text: \"@import\"},\n    { name: \"PAGE_SYM\", text: \"@page\"},\n    { name: \"MEDIA_SYM\", text: \"@media\"},\n    { name: \"FONT_FACE_SYM\", text: \"@font-face\"},\n    { name: \"CHARSET_SYM\", text: \"@charset\"},\n    { name: \"NAMESPACE_SYM\", text: \"@namespace\"},\n    //{ name: \"ATKEYWORD\"},\n\n    //important symbol\n    { name: \"IMPORTANT_SYM\"},\n\n    //measurements\n    { name: \"EMS\"},\n    { name: \"EXS\"},\n    { name: \"LENGTH\"},\n    { name: \"ANGLE\"},\n    { name: \"TIME\"},\n    { name: \"FREQ\"},\n    { name: \"DIMENSION\"},\n    { name: \"PERCENTAGE\"},\n    { name: \"NUMBER\"},\n    \n    //functions\n    { name: \"URI\"},\n    { name: \"FUNCTION\"},\n    \n    //Unicode ranges\n    { name: \"UNICODE_RANGE\"},\n    \n    /*\n     * The following token names are defined in CSS3 Selectors: http://www.w3.org/TR/css3-selectors/#selector-syntax\n     */    \n    \n    //invalid string\n    { name: \"INVALID\"},\n    \n    //combinators\n    { name: \"PLUS\", text: \"+\" },\n    { name: \"GREATER\", text: \">\"},\n    { name: \"COMMA\", text: \",\"},\n    { name: \"TILDE\", text: \"~\"},\n    \n    //modifier\n    { name: \"NOT\"},        \n    \n    /*\n     * Defined in CSS3 Paged Media\n     */\n    { name: \"TOPLEFTCORNER_SYM\", text: \"@top-left-corner\"},\n    { name: \"TOPLEFT_SYM\", text: \"@top-left\"},\n    { name: \"TOPCENTER_SYM\", text: \"@top-center\"},\n    { name: \"TOPRIGHT_SYM\", text: \"@top-right\"},\n    { name: \"TOPRIGHTCORNER_SYM\", text: \"@top-right-corner\"},\n    { name: \"BOTTOMLEFTCORNER_SYM\", text: \"@bottom-left-corner\"},\n    { name: \"BOTTOMLEFT_SYM\", text: \"@bottom-left\"},\n    { name: \"BOTTOMCENTER_SYM\", text: \"@bottom-center\"},\n    { name: \"BOTTOMRIGHT_SYM\", text: \"@bottom-right\"},\n    { name: \"BOTTOMRIGHTCORNER_SYM\", text: \"@bottom-right-corner\"},\n    { name: \"LEFTTOP_SYM\", text: \"@left-top\"},\n    { name: \"LEFTMIDDLE_SYM\", text: \"@left-middle\"},\n    { name: \"LEFTBOTTOM_SYM\", text: \"@left-bottom\"},\n    { name: \"RIGHTTOP_SYM\", text: \"@right-top\"},\n    { name: \"RIGHTMIDDLE_SYM\", text: \"@right-middle\"},\n    { name: \"RIGHTBOTTOM_SYM\", text: \"@right-bottom\"},\n\n    /*\n     * The following token names are defined in CSS3 Media Queries: http://www.w3.org/TR/css3-mediaqueries/#syntax\n     */\n    /*{ name: \"MEDIA_ONLY\", state: \"media\"},\n    { name: \"MEDIA_NOT\", state: \"media\"},\n    { name: \"MEDIA_AND\", state: \"media\"},*/\n    { name: \"RESOLUTION\", state: \"media\"},\n\n    /*\n     * The following token names are not defined in any CSS specification but are used by the lexer.\n     */\n    \n    //not a real token, but useful for stupid IE filters\n    { name: \"IE_FUNCTION\" },\n\n    //part of CSS3 grammar but not the Flex code\n    { name: \"CHAR\" },\n    \n    //TODO: Needed?\n    //Not defined as tokens, but might as well be\n    {\n        name: \"PIPE\",\n        text: \"|\"\n    },\n    {\n        name: \"SLASH\",\n        text: \"/\"\n    },\n    {\n        name: \"MINUS\",\n        text: \"-\"\n    },\n    {\n        name: \"STAR\",\n        text: \"*\"\n    },\n\n    {\n        name: \"LBRACE\",\n        text: \"{\"\n    },   \n    {\n        name: \"RBRACE\",\n        text: \"}\"\n    },      \n    {\n        name: \"LBRACKET\",\n        text: \"[\"\n    },   \n    {\n        name: \"RBRACKET\",\n        text: \"]\"\n    },    \n    {\n        name: \"EQUALS\",\n        text: \"=\"\n    },\n    {\n        name: \"COLON\",\n        text: \":\"\n    },    \n    {\n        name: \"SEMICOLON\",\n        text: \";\"\n    },    \n \n    {\n        name: \"LPAREN\",\n        text: \"(\"\n    },   \n    {\n        name: \"RPAREN\",\n        text: \")\"\n    },     \n    {\n        name: \"DOT\",\n        text: \".\"\n    }\n];\n\n(function(){\n\n    var nameMap = [],\n        typeMap = {};\n    \n    Tokens.UNKNOWN = -1;\n    Tokens.unshift({name:\"EOF\"});\n    for (var i=0, len = Tokens.length; i < len; i++){\n        nameMap.push(Tokens[i].name);\n        Tokens[Tokens[i].name] = i;\n        if (Tokens[i].text){\n            typeMap[Tokens[i].text] = i;\n        }\n    }\n    \n    Tokens.name = function(tt){\n        return nameMap[tt];\n    };\n    \n    Tokens.type = function(c){\n        return typeMap[c] || -1;\n    };\n\n})();\n\n\n\n\nparserlib.css = {\nColors              :Colors,    \nCombinator          :Combinator,                \nParser              :Parser,\nPropertyName        :PropertyName,\nPropertyValue       :PropertyValue,\nPropertyValuePart   :PropertyValuePart,\nMediaFeature        :MediaFeature,\nMediaQuery          :MediaQuery,\nSelector            :Selector,\nSelectorPart        :SelectorPart,\nSelectorSubPart     :SelectorSubPart,\nTokenStream         :TokenStream,\nTokens              :Tokens\n};\n})();\n/**\n * YUI Test Framework\n * @module yuitest\n */\n\n/**\n * The root namespace for YUI Test.\n * @class YUITest\n * @static\n */\n\nvar YUITest = {\n    version: \"@VERSION@\"\n};\n\n\n/**\n * Simple custom event implementation.\n * @namespace YUITest\n * @class EventTarget\n * @constructor\n */\nYUITest.EventTarget = function(){\n\n    /**\n     * Event handlers for the various events.\n     * @type Object\n     * @private\n     * @property _handlers\n     * @static\n     */\n    this._handlers = {};\n\n};\n\nYUITest.EventTarget.prototype = {\n\n    //restore prototype\n    constructor: YUITest.EventTarget,\n\n    //-------------------------------------------------------------------------\n    // Event Handling\n    //-------------------------------------------------------------------------\n\n    /**\n     * Adds a listener for a given event type.\n     * @param {String} type The type of event to add a listener for.\n     * @param {Function} listener The function to call when the event occurs.\n     * @return {void}\n     * @method attach\n     */\n    attach: function(type, listener){\n        if (typeof this._handlers[type] == \"undefined\"){\n            this._handlers[type] = [];\n        }\n\n        this._handlers[type].push(listener);\n    },\n\n    /**\n     * Adds a listener for a given event type.\n     * @param {String} type The type of event to add a listener for.\n     * @param {Function} listener The function to call when the event occurs.\n     * @return {void}\n     * @method subscribe\n     * @deprecated\n     */\n    subscribe: function(type, listener){\n        this.attach.apply(this, arguments);\n    },\n\n    /**\n     * Fires an event based on the passed-in object.\n     * @param {Object|String} event An object with at least a 'type' attribute\n     *      or a string indicating the event name.\n     * @return {void}\n     * @method fire\n     */\n    fire: function(event){\n        if (typeof event == \"string\"){\n            event = { type: event };\n        }\n        if (!event.target){\n            event.target = this;\n        }\n\n        if (!event.type){\n            throw new Error(\"Event object missing 'type' property.\");\n        }\n\n        if (this._handlers[event.type] instanceof Array){\n            var handlers = this._handlers[event.type];\n            for (var i=0, len=handlers.length; i < len; i++){\n                handlers[i].call(this, event);\n            }\n        }\n    },\n\n    /**\n     * Removes a listener for a given event type.\n     * @param {String} type The type of event to remove a listener from.\n     * @param {Function} listener The function to remove from the event.\n     * @return {void}\n     * @method detach\n     */\n    detach: function(type, listener){\n        if (this._handlers[type] instanceof Array){\n            var handlers = this._handlers[type];\n            for (var i=0, len=handlers.length; i < len; i++){\n                if (handlers[i] === listener){\n                    handlers.splice(i, 1);\n                    break;\n                }\n            }\n        }\n    },\n\n    /**\n     * Removes a listener for a given event type.\n     * @param {String} type The type of event to remove a listener from.\n     * @param {Function} listener The function to remove from the event.\n     * @return {void}\n     * @method unsubscribe\n     * @deprecated\n     */\n    unsubscribe: function(type, listener){\n        this.detach.apply(this, arguments);\n    }\n\n};\n\n\n/**\n * Object containing helper methods.\n * @namespace YUITest\n * @class Util\n * @static\n */\nYUITest.Util = {\n\n    /**\n     * Mixes the own properties from the supplier onto the\n     * receiver.\n     * @param {Object} receiver The object to receive the properties.\n     * @param {Object} supplier The object to supply the properties.\n     * @return {Object} The receiver that was passed in.\n     * @method mix\n     * @static\n     */\n    mix: function(receiver, supplier){\n\n        for (var prop in supplier){\n            if (supplier.hasOwnProperty(prop)){\n                receiver[prop] = supplier[prop];\n            }\n        }\n\n        return receiver;\n    },\n\n    /**\n     * Stub for JSON functionality. When the native JSON utility\n     * is available, it will be used. Otherwise, a stub object\n     * is created. Developers should override YUITest.Util.JSON\n     * when attempting to use it in environments where a native\n     * JSON utility is unavailable.\n     * @property JSON\n     * @type JSON\n     * @static\n     */\n    JSON: typeof JSON != \"undefined\" ? JSON : {\n        stringify: function(){\n            //TODO: Should include code to do this?\n            throw new Error(\"No JSON utility specified.\");\n        }\n    }\n\n};\n\n\n/**\n * Error is thrown whenever an assertion fails. It provides methods\n * to more easily get at error information and also provides a base class\n * from which more specific assertion errors can be derived.\n *\n * @param {String} message The message to display when the error occurs.\n * @namespace YUITest\n * @class AssertionError\n * @constructor\n */\nYUITest.AssertionError = function (message){\n\n    /**\n     * Error message. Must be duplicated to ensure browser receives it.\n     * @type String\n     * @property message\n     */\n    this.message = message;\n\n    /**\n     * The name of the error that occurred.\n     * @type String\n     * @property name\n     */\n    this.name = \"Assert Error\";\n};\n\nYUITest.AssertionError.prototype = {\n\n    //restore constructor\n    constructor: YUITest.AssertionError,\n\n    /**\n     * Returns a fully formatted error for an assertion failure. This should\n     * be overridden by all subclasses to provide specific information.\n     * @method getMessage\n     * @return {String} A string describing the error.\n     */\n    getMessage : function () {\n        return this.message;\n    },\n\n    /**\n     * Returns a string representation of the error.\n     * @method toString\n     * @return {String} A string representation of the error.\n     */\n    toString : function () {\n        return this.name + \": \" + this.getMessage();\n    }\n\n};\n\n/**\n * ComparisonFailure is subclass of Error that is thrown whenever\n * a comparison between two values fails. It provides mechanisms to retrieve\n * both the expected and actual value.\n *\n * @param {String} message The message to display when the error occurs.\n * @param {Object} expected The expected value.\n * @param {Object} actual The actual value that caused the assertion to fail.\n * @namespace YUITest\n * @extends AssertionError\n * @class ComparisonFailure\n * @constructor\n */\nYUITest.ComparisonFailure = function (message, expected, actual){\n\n    //call superclass\n    YUITest.AssertionError.call(this, message);\n\n    /**\n     * The expected value.\n     * @type Object\n     * @property expected\n     */\n    this.expected = expected;\n\n    /**\n     * The actual value.\n     * @type Object\n     * @property actual\n     */\n    this.actual = actual;\n\n    /**\n     * The name of the error that occurred.\n     * @type String\n     * @property name\n     */\n    this.name = \"ComparisonFailure\";\n\n};\n\n//inherit from YUITest.AssertionError\nYUITest.ComparisonFailure.prototype = new YUITest.AssertionError;\n\n//restore constructor\nYUITest.ComparisonFailure.prototype.constructor = YUITest.ComparisonFailure;\n\n/**\n * Returns a fully formatted error for an assertion failure. This message\n * provides information about the expected and actual values.\n * @method getMessage\n * @return {String} A string describing the error.\n */\nYUITest.ComparisonFailure.prototype.getMessage = function(){\n    return this.message + \"\\nExpected: \" + this.expected + \" (\" + (typeof this.expected) + \")\"  +\n            \"\\nActual: \" + this.actual + \" (\" + (typeof this.actual) + \")\";\n};\n\n/**\n * ShouldError is subclass of Error that is thrown whenever\n * a test is expected to throw an error but doesn't.\n *\n * @param {String} message The message to display when the error occurs.\n * @namespace YUITest\n * @extends AssertionError\n * @class ShouldError\n * @constructor\n */\nYUITest.ShouldError = function (message){\n\n    //call superclass\n    YUITest.AssertionError.call(this, message || \"This test should have thrown an error but didn't.\");\n\n    /**\n     * The name of the error that occurred.\n     * @type String\n     * @property name\n     */\n    this.name = \"ShouldError\";\n\n};\n\n//inherit from YUITest.AssertionError\nYUITest.ShouldError.prototype = new YUITest.AssertionError();\n\n//restore constructor\nYUITest.ShouldError.prototype.constructor = YUITest.ShouldError;\n\n/**\n * ShouldFail is subclass of AssertionError that is thrown whenever\n * a test was expected to fail but did not.\n *\n * @param {String} message The message to display when the error occurs.\n * @namespace YUITest\n * @extends YUITest.AssertionError\n * @class ShouldFail\n * @constructor\n */\nYUITest.ShouldFail = function (message){\n\n    //call superclass\n    YUITest.AssertionError.call(this, message || \"This test should fail but didn't.\");\n\n    /**\n     * The name of the error that occurred.\n     * @type String\n     * @property name\n     */\n    this.name = \"ShouldFail\";\n\n};\n\n//inherit from YUITest.AssertionError\nYUITest.ShouldFail.prototype = new YUITest.AssertionError();\n\n//restore constructor\nYUITest.ShouldFail.prototype.constructor = YUITest.ShouldFail;\n\n/**\n * UnexpectedError is subclass of AssertionError that is thrown whenever\n * an error occurs within the course of a test and the test was not expected\n * to throw an error.\n *\n * @param {Error} cause The unexpected error that caused this error to be\n *                      thrown.\n * @namespace YUITest\n * @extends YUITest.AssertionError\n * @class UnexpectedError\n * @constructor\n */\nYUITest.UnexpectedError = function (cause){\n\n    //call superclass\n    YUITest.AssertionError.call(this, \"Unexpected error: \" + cause.message);\n\n    /**\n     * The unexpected error that occurred.\n     * @type Error\n     * @property cause\n     */\n    this.cause = cause;\n\n    /**\n     * The name of the error that occurred.\n     * @type String\n     * @property name\n     */\n    this.name = \"UnexpectedError\";\n\n    /**\n     * Stack information for the error (if provided).\n     * @type String\n     * @property stack\n     */\n    this.stack = cause.stack;\n\n};\n\n//inherit from YUITest.AssertionError\nYUITest.UnexpectedError.prototype = new YUITest.AssertionError();\n\n//restore constructor\nYUITest.UnexpectedError.prototype.constructor = YUITest.UnexpectedError;\n\n/**\n * UnexpectedValue is subclass of Error that is thrown whenever\n * a value was unexpected in its scope. This typically means that a test\n * was performed to determine that a value was *not* equal to a certain\n * value.\n *\n * @param {String} message The message to display when the error occurs.\n * @param {Object} unexpected The unexpected value.\n * @namespace YUITest\n * @extends AssertionError\n * @class UnexpectedValue\n * @constructor\n */\nYUITest.UnexpectedValue = function (message, unexpected){\n\n    //call superclass\n    YUITest.AssertionError.call(this, message);\n\n    /**\n     * The unexpected value.\n     * @type Object\n     * @property unexpected\n     */\n    this.unexpected = unexpected;\n\n    /**\n     * The name of the error that occurred.\n     * @type String\n     * @property name\n     */\n    this.name = \"UnexpectedValue\";\n\n};\n\n//inherit from YUITest.AssertionError\nYUITest.UnexpectedValue.prototype = new YUITest.AssertionError();\n\n//restore constructor\nYUITest.UnexpectedValue.prototype.constructor = YUITest.UnexpectedValue;\n\n/**\n * Returns a fully formatted error for an assertion failure. This message\n * provides information about the expected and actual values.\n * @method getMessage\n * @return {String} A string describing the error.\n */\nYUITest.UnexpectedValue.prototype.getMessage = function(){\n    return this.message + \"\\nUnexpected: \" + this.unexpected + \" (\" + (typeof this.unexpected) + \") \";\n};\n\n\n/**\n * Represents a stoppage in test execution to wait for an amount of time before\n * continuing.\n * @param {Function} segment A function to run when the wait is over.\n * @param {int} delay The number of milliseconds to wait before running the code.\n * @class Wait\n * @namespace Test\n * @constructor\n *\n */\nYUITest.Wait = function (segment, delay) {\n\n    /**\n     * The segment of code to run when the wait is over.\n     * @type Function\n     * @property segment\n     */\n    this.segment = (typeof segment == \"function\" ? segment : null);\n\n    /**\n     * The delay before running the segment of code.\n     * @type int\n     * @property delay\n     */\n    this.delay = (typeof delay == \"number\" ? delay : 0);\n};\n\n\n/**\n * The Assert object provides functions to test JavaScript values against\n * known and expected results. Whenever a comparison (assertion) fails,\n * an error is thrown.\n * @namespace YUITest\n * @class Assert\n * @static\n */\nYUITest.Assert = {\n\n    /**\n     * The number of assertions performed.\n     * @property _asserts\n     * @type int\n     * @private\n     */\n    _asserts: 0,\n\n    //-------------------------------------------------------------------------\n    // Helper Methods\n    //-------------------------------------------------------------------------\n\n    /**\n     * Formats a message so that it can contain the original assertion message\n     * in addition to the custom message.\n     * @param {String} customMessage The message passed in by the developer.\n     * @param {String} defaultMessage The message created by the error by default.\n     * @return {String} The final error message, containing either or both.\n     * @protected\n     * @static\n     * @method _formatMessage\n     */\n    _formatMessage : function (customMessage, defaultMessage) {\n        if (typeof customMessage == \"string\" && customMessage.length > 0){\n            return customMessage.replace(\"{message}\", defaultMessage);\n        } else {\n            return defaultMessage;\n        }\n    },\n\n    /**\n     * Returns the number of assertions that have been performed.\n     * @method _getCount\n     * @protected\n     * @static\n     */\n    _getCount: function(){\n        return this._asserts;\n    },\n\n    /**\n     * Increments the number of assertions that have been performed.\n     * @method _increment\n     * @protected\n     * @static\n     */\n    _increment: function(){\n        this._asserts++;\n    },\n\n    /**\n     * Resets the number of assertions that have been performed to 0.\n     * @method _reset\n     * @protected\n     * @static\n     */\n    _reset: function(){\n        this._asserts = 0;\n    },\n\n    //-------------------------------------------------------------------------\n    // Generic Assertion Methods\n    //-------------------------------------------------------------------------\n\n    /**\n     * Forces an assertion error to occur.\n     * @param {String} message (Optional) The message to display with the failure.\n     * @method fail\n     * @static\n     */\n    fail : function (message) {\n        throw new YUITest.AssertionError(YUITest.Assert._formatMessage(message, \"Test force-failed.\"));\n    },\n\n    //-------------------------------------------------------------------------\n    // Equality Assertion Methods\n    //-------------------------------------------------------------------------\n\n    /**\n     * Asserts that a value is equal to another. This uses the double equals sign\n     * so type cohersion may occur.\n     * @param {Object} expected The expected value.\n     * @param {Object} actual The actual value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method areEqual\n     * @static\n     */\n    areEqual : function (expected, actual, message) {\n        YUITest.Assert._increment();\n        if (expected != actual) {\n            throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, \"Values should be equal.\"), expected, actual);\n        }\n    },\n\n    /**\n     * Asserts that a value is not equal to another. This uses the double equals sign\n     * so type cohersion may occur.\n     * @param {Object} unexpected The unexpected value.\n     * @param {Object} actual The actual value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method areNotEqual\n     * @static\n     */\n    areNotEqual : function (unexpected, actual,\n                         message) {\n        YUITest.Assert._increment();\n        if (unexpected == actual) {\n            throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, \"Values should not be equal.\"), unexpected);\n        }\n    },\n\n    /**\n     * Asserts that a value is not the same as another. This uses the triple equals sign\n     * so no type cohersion may occur.\n     * @param {Object} unexpected The unexpected value.\n     * @param {Object} actual The actual value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method areNotSame\n     * @static\n     */\n    areNotSame : function (unexpected, actual, message) {\n        YUITest.Assert._increment();\n        if (unexpected === actual) {\n            throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, \"Values should not be the same.\"), unexpected);\n        }\n    },\n\n    /**\n     * Asserts that a value is the same as another. This uses the triple equals sign\n     * so no type cohersion may occur.\n     * @param {Object} expected The expected value.\n     * @param {Object} actual The actual value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method areSame\n     * @static\n     */\n    areSame : function (expected, actual, message) {\n        YUITest.Assert._increment();\n        if (expected !== actual) {\n            throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, \"Values should be the same.\"), expected, actual);\n        }\n    },\n\n    //-------------------------------------------------------------------------\n    // Boolean Assertion Methods\n    //-------------------------------------------------------------------------\n\n    /**\n     * Asserts that a value is false. This uses the triple equals sign\n     * so no type cohersion may occur.\n     * @param {Object} actual The actual value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isFalse\n     * @static\n     */\n    isFalse : function (actual, message) {\n        YUITest.Assert._increment();\n        if (false !== actual) {\n            throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, \"Value should be false.\"), false, actual);\n        }\n    },\n\n    /**\n     * Asserts that a value is true. This uses the triple equals sign\n     * so no type cohersion may occur.\n     * @param {Object} actual The actual value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isTrue\n     * @static\n     */\n    isTrue : function (actual, message) {\n        YUITest.Assert._increment();\n        if (true !== actual) {\n            throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, \"Value should be true.\"), true, actual);\n        }\n\n    },\n\n    //-------------------------------------------------------------------------\n    // Special Value Assertion Methods\n    //-------------------------------------------------------------------------\n\n    /**\n     * Asserts that a value is not a number.\n     * @param {Object} actual The value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isNaN\n     * @static\n     */\n    isNaN : function (actual, message){\n        YUITest.Assert._increment();\n        if (!isNaN(actual)){\n            throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, \"Value should be NaN.\"), NaN, actual);\n        }\n    },\n\n    /**\n     * Asserts that a value is not the special NaN value.\n     * @param {Object} actual The value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isNotNaN\n     * @static\n     */\n    isNotNaN : function (actual, message){\n        YUITest.Assert._increment();\n        if (isNaN(actual)){\n            throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, \"Values should not be NaN.\"), NaN);\n        }\n    },\n\n    /**\n     * Asserts that a value is not null. This uses the triple equals sign\n     * so no type cohersion may occur.\n     * @param {Object} actual The actual value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isNotNull\n     * @static\n     */\n    isNotNull : function (actual, message) {\n        YUITest.Assert._increment();\n        if (actual === null) {\n            throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, \"Values should not be null.\"), null);\n        }\n    },\n\n    /**\n     * Asserts that a value is not undefined. This uses the triple equals sign\n     * so no type cohersion may occur.\n     * @param {Object} actual The actual value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isNotUndefined\n     * @static\n     */\n    isNotUndefined : function (actual, message) {\n        YUITest.Assert._increment();\n        if (typeof actual == \"undefined\") {\n            throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, \"Value should not be undefined.\"), undefined);\n        }\n    },\n\n    /**\n     * Asserts that a value is null. This uses the triple equals sign\n     * so no type cohersion may occur.\n     * @param {Object} actual The actual value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isNull\n     * @static\n     */\n    isNull : function (actual, message) {\n        YUITest.Assert._increment();\n        if (actual !== null) {\n            throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, \"Value should be null.\"), null, actual);\n        }\n    },\n\n    /**\n     * Asserts that a value is undefined. This uses the triple equals sign\n     * so no type cohersion may occur.\n     * @param {Object} actual The actual value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isUndefined\n     * @static\n     */\n    isUndefined : function (actual, message) {\n        YUITest.Assert._increment();\n        if (typeof actual != \"undefined\") {\n            throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, \"Value should be undefined.\"), undefined, actual);\n        }\n    },\n\n    //--------------------------------------------------------------------------\n    // Instance Assertion Methods\n    //--------------------------------------------------------------------------\n\n    /**\n     * Asserts that a value is an array.\n     * @param {Object} actual The value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isArray\n     * @static\n     */\n    isArray : function (actual, message) {\n        YUITest.Assert._increment();\n        var shouldFail = false;\n        if (Array.isArray){\n            shouldFail = !Array.isArray(actual);\n        } else {\n            shouldFail = Object.prototype.toString.call(actual) != \"[object Array]\";\n        }\n        if (shouldFail){\n            throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, \"Value should be an array.\"), actual);\n        }\n    },\n\n    /**\n     * Asserts that a value is a Boolean.\n     * @param {Object} actual The value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isBoolean\n     * @static\n     */\n    isBoolean : function (actual, message) {\n        YUITest.Assert._increment();\n        if (typeof actual != \"boolean\"){\n            throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, \"Value should be a Boolean.\"), actual);\n        }\n    },\n\n    /**\n     * Asserts that a value is a function.\n     * @param {Object} actual The value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isFunction\n     * @static\n     */\n    isFunction : function (actual, message) {\n        YUITest.Assert._increment();\n        if (!(actual instanceof Function)){\n            throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, \"Value should be a function.\"), actual);\n        }\n    },\n\n    /**\n     * Asserts that a value is an instance of a particular object. This may return\n     * incorrect results when comparing objects from one frame to constructors in\n     * another frame. For best results, don't use in a cross-frame manner.\n     * @param {Function} expected The function that the object should be an instance of.\n     * @param {Object} actual The object to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isInstanceOf\n     * @static\n     */\n    isInstanceOf : function (expected, actual, message) {\n        YUITest.Assert._increment();\n        if (!(actual instanceof expected)){\n            throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, \"Value isn't an instance of expected type.\"), expected, actual);\n        }\n    },\n\n    /**\n     * Asserts that a value is a number.\n     * @param {Object} actual The value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isNumber\n     * @static\n     */\n    isNumber : function (actual, message) {\n        YUITest.Assert._increment();\n        if (typeof actual != \"number\"){\n            throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, \"Value should be a number.\"), actual);\n        }\n    },\n\n    /**\n     * Asserts that a value is an object.\n     * @param {Object} actual The value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isObject\n     * @static\n     */\n    isObject : function (actual, message) {\n        YUITest.Assert._increment();\n        if (!actual || (typeof actual != \"object\" && typeof actual != \"function\")){\n            throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, \"Value should be an object.\"), actual);\n        }\n    },\n\n    /**\n     * Asserts that a value is a string.\n     * @param {Object} actual The value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isString\n     * @static\n     */\n    isString : function (actual, message) {\n        YUITest.Assert._increment();\n        if (typeof actual != \"string\"){\n            throw new YUITest.UnexpectedValue(YUITest.Assert._formatMessage(message, \"Value should be a string.\"), actual);\n        }\n    },\n\n    /**\n     * Asserts that a value is of a particular type.\n     * @param {String} expectedType The expected type of the variable.\n     * @param {Object} actualValue The actual value to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isTypeOf\n     * @static\n     */\n    isTypeOf : function (expectedType, actualValue, message){\n        YUITest.Assert._increment();\n        if (typeof actualValue != expectedType){\n            throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, \"Value should be of type \" + expectedType + \".\"), expectedType, typeof actualValue);\n        }\n    },\n\n    //--------------------------------------------------------------------------\n    // Error Detection Methods\n    //--------------------------------------------------------------------------\n\n    /**\n     * Asserts that executing a particular method should throw an error of\n     * a specific type. This is a replacement for _should.error.\n     * @param {String|Function|Object} expectedError If a string, this\n     *      is the error message that the error must have; if a function, this\n     *      is the constructor that should have been used to create the thrown\n     *      error; if an object, this is an instance of a particular error type\n     *      with a specific error message (both must match).\n     * @param {Function} method The method to execute that should throw the error.\n     * @param {String} message (Optional) The message to display if the assertion\n     *      fails.\n     * @method throwsError\n     * @return {void}\n     * @static\n     */\n    throwsError: function(expectedError, method, message){\n        YUITest.Assert._increment();\n        var error = false;\n\n        try {\n            method();\n        } catch (thrown) {\n\n            //check to see what type of data we have\n            if (typeof expectedError == \"string\"){\n\n                //if it's a string, check the error message\n                if (thrown.message != expectedError){\n                    error = true;\n                }\n            } else if (typeof expectedError == \"function\"){\n\n                //if it's a function, see if the error is an instance of it\n                if (!(thrown instanceof expectedError)){\n                    error = true;\n                }\n\n            } else if (typeof expectedError == \"object\" && expectedError !== null){\n\n                //if it's an object, check the instance and message\n                if (!(thrown instanceof expectedError.constructor) ||\n                        thrown.message != expectedError.message){\n                    error = true;\n                }\n\n            } else { //if it gets here, the argument could be wrong\n                error = true;\n            }\n\n            if (error){\n                throw new YUITest.UnexpectedError(thrown);\n            } else {\n                return;\n            }\n        }\n\n        //if it reaches here, the error wasn't thrown, which is a bad thing\n        throw new YUITest.AssertionError(YUITest.Assert._formatMessage(message, \"Error should have been thrown.\"));\n    }\n\n};\n\n\n/**\n * The ArrayAssert object provides functions to test JavaScript array objects\n * for a variety of cases.\n * @namespace YUITest\n * @class ArrayAssert\n * @static\n */\n\nYUITest.ArrayAssert = {\n\n    //=========================================================================\n    // Private methods\n    //=========================================================================\n\n    /**\n     * Simple indexOf() implementation for an array. Defers to native\n     * if available.\n     * @param {Array} haystack The array to search.\n     * @param {Variant} needle The value to locate.\n     * @return {int} The index of the needle if found or -1 if not.\n     * @method _indexOf\n     * @private\n     */\n    _indexOf: function(haystack, needle){\n        if (haystack.indexOf){\n            return haystack.indexOf(needle);\n        } else {\n            for (var i=0; i < haystack.length; i++){\n                if (haystack[i] === needle){\n                    return i;\n                }\n            }\n            return -1;\n        }\n    },\n\n    /**\n     * Simple some() implementation for an array. Defers to native\n     * if available.\n     * @param {Array} haystack The array to search.\n     * @param {Function} matcher The function to run on each value.\n     * @return {Boolean} True if any value, when run through the matcher,\n     *      returns true.\n     * @method _some\n     * @private\n     */\n    _some: function(haystack, matcher){\n        if (haystack.some){\n            return haystack.some(matcher);\n        } else {\n            for (var i=0; i < haystack.length; i++){\n                if (matcher(haystack[i])){\n                    return true;\n                }\n            }\n            return false;\n        }\n    },\n\n    /**\n     * Asserts that a value is present in an array. This uses the triple equals\n     * sign so no type cohersion may occur.\n     * @param {Object} needle The value that is expected in the array.\n     * @param {Array} haystack An array of values.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method contains\n     * @static\n     */\n    contains : function (needle, haystack,\n                           message) {\n\n        YUITest.Assert._increment();\n\n        if (this._indexOf(haystack, needle) == -1){\n            YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Value \" + needle + \" (\" + (typeof needle) + \") not found in array [\" + haystack + \"].\"));\n        }\n    },\n\n    /**\n     * Asserts that a set of values are present in an array. This uses the triple equals\n     * sign so no type cohersion may occur. For this assertion to pass, all values must\n     * be found.\n     * @param {Object[]} needles An array of values that are expected in the array.\n     * @param {Array} haystack An array of values to check.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method containsItems\n     * @static\n     */\n    containsItems : function (needles, haystack,\n                           message) {\n        YUITest.Assert._increment();\n\n        //begin checking values\n        for (var i=0; i < needles.length; i++){\n            if (this._indexOf(haystack, needles[i]) == -1){\n                YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Value \" + needles[i] + \" (\" + (typeof needles[i]) + \") not found in array [\" + haystack + \"].\"));\n            }\n        }\n    },\n\n    /**\n     * Asserts that a value matching some condition is present in an array. This uses\n     * a function to determine a match.\n     * @param {Function} matcher A function that returns true if the items matches or false if not.\n     * @param {Array} haystack An array of values.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method containsMatch\n     * @static\n     */\n    containsMatch : function (matcher, haystack,\n                           message) {\n\n        YUITest.Assert._increment();\n        //check for valid matcher\n        if (typeof matcher != \"function\"){\n            throw new TypeError(\"ArrayAssert.containsMatch(): First argument must be a function.\");\n        }\n\n        if (!this._some(haystack, matcher)){\n            YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"No match found in array [\" + haystack + \"].\"));\n        }\n    },\n\n    /**\n     * Asserts that a value is not present in an array. This uses the triple equals\n     * Asserts that a value is not present in an array. This uses the triple equals\n     * sign so no type cohersion may occur.\n     * @param {Object} needle The value that is expected in the array.\n     * @param {Array} haystack An array of values.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method doesNotContain\n     * @static\n     */\n    doesNotContain : function (needle, haystack,\n                           message) {\n\n        YUITest.Assert._increment();\n\n        if (this._indexOf(haystack, needle) > -1){\n            YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Value found in array [\" + haystack + \"].\"));\n        }\n    },\n\n    /**\n     * Asserts that a set of values are not present in an array. This uses the triple equals\n     * sign so no type cohersion may occur. For this assertion to pass, all values must\n     * not be found.\n     * @param {Object[]} needles An array of values that are not expected in the array.\n     * @param {Array} haystack An array of values to check.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method doesNotContainItems\n     * @static\n     */\n    doesNotContainItems : function (needles, haystack,\n                           message) {\n\n        YUITest.Assert._increment();\n\n        for (var i=0; i < needles.length; i++){\n            if (this._indexOf(haystack, needles[i]) > -1){\n                YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Value found in array [\" + haystack + \"].\"));\n            }\n        }\n\n    },\n\n    /**\n     * Asserts that no values matching a condition are present in an array. This uses\n     * a function to determine a match.\n     * @param {Function} matcher A function that returns true if the item matches or false if not.\n     * @param {Array} haystack An array of values.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method doesNotContainMatch\n     * @static\n     */\n    doesNotContainMatch : function (matcher, haystack,\n                           message) {\n\n        YUITest.Assert._increment();\n\n        //check for valid matcher\n        if (typeof matcher != \"function\"){\n            throw new TypeError(\"ArrayAssert.doesNotContainMatch(): First argument must be a function.\");\n        }\n\n        if (this._some(haystack, matcher)){\n            YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Value found in array [\" + haystack + \"].\"));\n        }\n    },\n\n    /**\n     * Asserts that the given value is contained in an array at the specified index.\n     * This uses the triple equals sign so no type cohersion will occur.\n     * @param {Object} needle The value to look for.\n     * @param {Array} haystack The array to search in.\n     * @param {int} index The index at which the value should exist.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method indexOf\n     * @static\n     */\n    indexOf : function (needle, haystack, index, message) {\n\n        YUITest.Assert._increment();\n\n        //try to find the value in the array\n        for (var i=0; i < haystack.length; i++){\n            if (haystack[i] === needle){\n                if (index != i){\n                    YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Value exists at index \" + i + \" but should be at index \" + index + \".\"));\n                }\n                return;\n            }\n        }\n\n        //if it makes it here, it wasn't found at all\n        YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Value doesn't exist in array [\" + haystack + \"].\"));\n    },\n\n    /**\n     * Asserts that the values in an array are equal, and in the same position,\n     * as values in another array. This uses the double equals sign\n     * so type cohersion may occur. Note that the array objects themselves\n     * need not be the same for this test to pass.\n     * @param {Array} expected An array of the expected values.\n     * @param {Array} actual Any array of the actual values.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method itemsAreEqual\n     * @static\n     */\n    itemsAreEqual : function (expected, actual,\n                           message) {\n\n        YUITest.Assert._increment();\n\n        //first check array length\n        if (expected.length != actual.length){\n            YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Array should have a length of \" + expected.length + \" but has a length of \" + actual.length));\n        }\n\n        //begin checking values\n        for (var i=0; i < expected.length; i++){\n            if (expected[i] != actual[i]){\n                throw new YUITest.Assert.ComparisonFailure(YUITest.Assert._formatMessage(message, \"Values in position \" + i + \" are not equal.\"), expected[i], actual[i]);\n            }\n        }\n    },\n\n    /**\n     * Asserts that the values in an array are equivalent, and in the same position,\n     * as values in another array. This uses a function to determine if the values\n     * are equivalent. Note that the array objects themselves\n     * need not be the same for this test to pass.\n     * @param {Array} expected An array of the expected values.\n     * @param {Array} actual Any array of the actual values.\n     * @param {Function} comparator A function that returns true if the values are equivalent\n     *      or false if not.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @return {Void}\n     * @method itemsAreEquivalent\n     * @static\n     */\n    itemsAreEquivalent : function (expected, actual,\n                           comparator, message) {\n\n        YUITest.Assert._increment();\n\n        //make sure the comparator is valid\n        if (typeof comparator != \"function\"){\n            throw new TypeError(\"ArrayAssert.itemsAreEquivalent(): Third argument must be a function.\");\n        }\n\n        //first check array length\n        if (expected.length != actual.length){\n            YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Array should have a length of \" + expected.length + \" but has a length of \" + actual.length));\n        }\n\n        //begin checking values\n        for (var i=0; i < expected.length; i++){\n            if (!comparator(expected[i], actual[i])){\n                throw new YUITest.Assert.ComparisonFailure(YUITest.Assert._formatMessage(message, \"Values in position \" + i + \" are not equivalent.\"), expected[i], actual[i]);\n            }\n        }\n    },\n\n    /**\n     * Asserts that an array is empty.\n     * @param {Array} actual The array to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isEmpty\n     * @static\n     */\n    isEmpty : function (actual, message) {\n        YUITest.Assert._increment();\n        if (actual.length > 0){\n            YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Array should be empty.\"));\n        }\n    },\n\n    /**\n     * Asserts that an array is not empty.\n     * @param {Array} actual The array to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method isNotEmpty\n     * @static\n     */\n    isNotEmpty : function (actual, message) {\n        YUITest.Assert._increment();\n        if (actual.length === 0){\n            YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Array should not be empty.\"));\n        }\n    },\n\n    /**\n     * Asserts that the values in an array are the same, and in the same position,\n     * as values in another array. This uses the triple equals sign\n     * so no type cohersion will occur. Note that the array objects themselves\n     * need not be the same for this test to pass.\n     * @param {Array} expected An array of the expected values.\n     * @param {Array} actual Any array of the actual values.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method itemsAreSame\n     * @static\n     */\n    itemsAreSame : function (expected, actual,\n                          message) {\n\n        YUITest.Assert._increment();\n\n        //first check array length\n        if (expected.length != actual.length){\n            YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Array should have a length of \" + expected.length + \" but has a length of \" + actual.length));\n        }\n\n        //begin checking values\n        for (var i=0; i < expected.length; i++){\n            if (expected[i] !== actual[i]){\n                throw new YUITest.Assert.ComparisonFailure(YUITest.Assert._formatMessage(message, \"Values in position \" + i + \" are not the same.\"), expected[i], actual[i]);\n            }\n        }\n    },\n\n    /**\n     * Asserts that the given value is contained in an array at the specified index,\n     * starting from the back of the array.\n     * This uses the triple equals sign so no type cohersion will occur.\n     * @param {Object} needle The value to look for.\n     * @param {Array} haystack The array to search in.\n     * @param {int} index The index at which the value should exist.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method lastIndexOf\n     * @static\n     */\n    lastIndexOf : function (needle, haystack, index, message) {\n\n        //try to find the value in the array\n        for (var i=haystack.length; i >= 0; i--){\n            if (haystack[i] === needle){\n                if (index != i){\n                    YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Value exists at index \" + i + \" but should be at index \" + index + \".\"));\n                }\n                return;\n            }\n        }\n\n        //if it makes it here, it wasn't found at all\n        YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Value doesn't exist in array.\"));\n    }\n\n};\n\n\n/**\n * The ObjectAssert object provides functions to test JavaScript objects\n * for a variety of cases.\n * @namespace YUITest\n * @class ObjectAssert\n * @static\n */\nYUITest.ObjectAssert = {\n\n    /**\n     * Asserts that an object has all of the same properties\n     * and property values as the other.\n     * @param {Object} expected The object with all expected properties and values.\n     * @param {Object} actual The object to inspect.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method areEqual\n     * @static\n     * @deprecated\n     */\n    areEqual: function(expected, actual, message) {\n        YUITest.Assert._increment();\n\n        for (var name in expected){\n            if (expected.hasOwnProperty(name)){\n                if (expected[name] != actual[name]){\n                    throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, \"Values should be equal for property \" + name), expected[name], actual[name]);\n                }\n            }\n        }\n    },\n\n    /**\n     * Asserts that an object has a property with the given name.\n     * @param {String} propertyName The name of the property to test.\n     * @param {Object} object The object to search.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method hasKey\n     * @static\n     * @deprecated Use ownsOrInheritsKey() instead\n     */\n    hasKey: function (propertyName, object, message) {\n        YUITest.ObjectAssert.ownsOrInheritsKey(propertyName, object, message);\n    },\n\n    /**\n     * Asserts that an object has all properties of a reference object.\n     * @param {Array} properties An array of property names that should be on the object.\n     * @param {Object} object The object to search.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method hasKeys\n     * @static\n     * @deprecated Use ownsOrInheritsKeys() instead\n     */\n    hasKeys: function (properties, object, message) {\n        YUITest.ObjectAssert.ownsOrInheritsKeys(properties, objects, message);\n    },\n\n    /**\n     * Asserts that a property with the given name exists on an object's prototype.\n     * @param {String} propertyName The name of the property to test.\n     * @param {Object} object The object to search.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method inheritsKey\n     * @static\n     */\n    inheritsKey: function (propertyName, object, message) {\n        YUITest.Assert._increment();\n        if (!(propertyName in object && !object.hasOwnProperty(propertyName))){\n            YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Property '\" + propertyName + \"' not found on object instance.\"));\n        }\n    },\n\n    /**\n     * Asserts that all properties exist on an object prototype.\n     * @param {Array} properties An array of property names that should be on the object.\n     * @param {Object} object The object to search.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method inheritsKeys\n     * @static\n     */\n    inheritsKeys: function (properties, object, message) {\n        YUITest.Assert._increment();\n        for (var i=0; i < properties.length; i++){\n            if (!(propertyName in object && !object.hasOwnProperty(properties[i]))){\n                YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Property '\" + properties[i] + \"' not found on object instance.\"));\n            }\n        }\n    },\n\n    /**\n     * Asserts that a property with the given name exists on an object instance (not on its prototype).\n     * @param {String} propertyName The name of the property to test.\n     * @param {Object} object The object to search.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method ownsKey\n     * @static\n     */\n    ownsKey: function (propertyName, object, message) {\n        YUITest.Assert._increment();\n        if (!object.hasOwnProperty(propertyName)){\n            YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Property '\" + propertyName + \"' not found on object instance.\"));\n        }\n    },\n\n    /**\n     * Asserts that all properties exist on an object instance (not on its prototype).\n     * @param {Array} properties An array of property names that should be on the object.\n     * @param {Object} object The object to search.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method ownsKeys\n     * @static\n     */\n    ownsKeys: function (properties, object, message) {\n        YUITest.Assert._increment();\n        for (var i=0; i < properties.length; i++){\n            if (!object.hasOwnProperty(properties[i])){\n                YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Property '\" + properties[i] + \"' not found on object instance.\"));\n            }\n        }\n    },\n\n    /**\n     * Asserts that an object owns no properties.\n     * @param {Object} object The object to check.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method ownsNoKeys\n     * @static\n     */\n    ownsNoKeys : function (object, message) {\n        YUITest.Assert._increment();\n        var count = 0,\n            name;\n        for (name in object){\n            if (object.hasOwnProperty(name)){\n                count++;\n            }\n        }\n\n        if (count !== 0){\n            YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Object owns \" + count + \" properties but should own none.\"));\n        }\n\n    },\n\n    /**\n     * Asserts that an object has a property with the given name.\n     * @param {String} propertyName The name of the property to test.\n     * @param {Object} object The object to search.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method ownsOrInheritsKey\n     * @static\n     */\n    ownsOrInheritsKey: function (propertyName, object, message) {\n        YUITest.Assert._increment();\n        if (!(propertyName in object)){\n            YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Property '\" + propertyName + \"' not found on object.\"));\n        }\n    },\n\n    /**\n     * Asserts that an object has all properties of a reference object.\n     * @param {Array} properties An array of property names that should be on the object.\n     * @param {Object} object The object to search.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method ownsOrInheritsKeys\n     * @static\n     */\n    ownsOrInheritsKeys: function (properties, object, message) {\n        YUITest.Assert._increment();\n        for (var i=0; i < properties.length; i++){\n            if (!(properties[i] in object)){\n                YUITest.Assert.fail(YUITest.Assert._formatMessage(message, \"Property '\" + properties[i] + \"' not found on object.\"));\n            }\n        }\n    }\n};\n\n\n\n/**\n * The DateAssert object provides functions to test JavaScript Date objects\n * for a variety of cases.\n * @namespace  YUITest\n * @class DateAssert\n * @static\n */\n\nYUITest.DateAssert = {\n\n    /**\n     * Asserts that a date's month, day, and year are equal to another date's.\n     * @param {Date} expected The expected date.\n     * @param {Date} actual The actual date to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method datesAreEqual\n     * @static\n     */\n    datesAreEqual : function (expected, actual, message){\n        YUITest.Assert._increment();\n        if (expected instanceof Date && actual instanceof Date){\n            var msg = \"\";\n\n            //check years first\n            if (expected.getFullYear() != actual.getFullYear()){\n                msg = \"Years should be equal.\";\n            }\n\n            //now check months\n            if (expected.getMonth() != actual.getMonth()){\n                msg = \"Months should be equal.\";\n            }\n\n            //last, check the day of the month\n            if (expected.getDate() != actual.getDate()){\n                msg = \"Days of month should be equal.\";\n            }\n\n            if (msg.length){\n                throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, msg), expected, actual);\n            }\n        } else {\n            throw new TypeError(\"YUITest.DateAssert.datesAreEqual(): Expected and actual values must be Date objects.\");\n        }\n    },\n\n    /**\n     * Asserts that a date's hour, minutes, and seconds are equal to another date's.\n     * @param {Date} expected The expected date.\n     * @param {Date} actual The actual date to test.\n     * @param {String} message (Optional) The message to display if the assertion fails.\n     * @method timesAreEqual\n     * @static\n     */\n    timesAreEqual : function (expected, actual, message){\n        YUITest.Assert._increment();\n        if (expected instanceof Date && actual instanceof Date){\n            var msg = \"\";\n\n            //check hours first\n            if (expected.getHours() != actual.getHours()){\n                msg = \"Hours should be equal.\";\n            }\n\n            //now check minutes\n            if (expected.getMinutes() != actual.getMinutes()){\n                msg = \"Minutes should be equal.\";\n            }\n\n            //last, check the seconds\n            if (expected.getSeconds() != actual.getSeconds()){\n                msg = \"Seconds should be equal.\";\n            }\n\n            if (msg.length){\n                throw new YUITest.ComparisonFailure(YUITest.Assert._formatMessage(message, msg), expected, actual);\n            }\n        } else {\n            throw new TypeError(\"YUITest.DateAssert.timesAreEqual(): Expected and actual values must be Date objects.\");\n        }\n    }\n\n};\n\n/**\n * Creates a new mock object.\n * @namespace YUITest\n * @class Mock\n * @constructor\n * @param {Object} template (Optional) An object whose methods\n *      should be stubbed out on the mock object.\n */\nYUITest.Mock = function(template){\n\n    //use blank object is nothing is passed in\n    template = template || {};\n\n    var mock,\n        name;\n\n    //try to create mock that keeps prototype chain intact\n    //fails in the case of ActiveX objects\n    try {\n        function f(){}\n        f.prototype = template;\n        mock = new f();\n    } catch (ex) {\n        mock = {};\n    }\n\n    //create stubs for all methods\n    for (name in template){\n        if (template.hasOwnProperty(name)){\n            if (typeof template[name] == \"function\"){\n                mock[name] = function(name){\n                    return function(){\n                        YUITest.Assert.fail(\"Method \" + name + \"() was called but was not expected to be.\");\n                    };\n                }(name);\n            }\n        }\n    }\n\n    //return it\n    return mock;\n};\n\n/**\n * Assigns an expectation to a mock object. This is used to create\n * methods and properties on the mock object that are monitored for\n * calls and changes, respectively.\n * @param {Object} mock The object to add the expectation to.\n * @param {Object} expectation An object defining the expectation. For\n *      a method, the keys \"method\" and \"args\" are required with\n *      an optional \"returns\" key available. For properties, the keys\n *      \"property\" and \"value\" are required.\n * @return {void}\n * @method expect\n * @static\n */\nYUITest.Mock.expect = function(mock /*:Object*/, expectation /*:Object*/){\n\n    //make sure there's a place to store the expectations\n    if (!mock.__expectations) {\n        mock.__expectations = {};\n    }\n\n    //method expectation\n    if (expectation.method){\n        var name = expectation.method,\n            args = expectation.args || [],\n            result = expectation.returns,\n            callCount = (typeof expectation.callCount == \"number\") ? expectation.callCount : 1,\n            error = expectation.error,\n            run = expectation.run || function(){},\n            i;\n\n        //save expectations\n        mock.__expectations[name] = expectation;\n        expectation.callCount = callCount;\n        expectation.actualCallCount = 0;\n\n        //process arguments\n        for (i=0; i < args.length; i++){\n             if (!(args[i] instanceof YUITest.Mock.Value)){\n                args[i] = YUITest.Mock.Value(YUITest.Assert.areSame, [args[i]], \"Argument \" + i + \" of \" + name + \"() is incorrect.\");\n            }\n        }\n\n        //if the method is expected to be called\n        if (callCount > 0){\n            mock[name] = function(){\n                try {\n                    expectation.actualCallCount++;\n                    YUITest.Assert.areEqual(args.length, arguments.length, \"Method \" + name + \"() passed incorrect number of arguments.\");\n                    for (var i=0, len=args.length; i < len; i++){\n                        args[i].verify(arguments[i]);\n                    }\n\n                    run.apply(this, arguments);\n\n                    if (error){\n                        throw error;\n                    }\n                } catch (ex){\n                    //route through TestRunner for proper handling\n                    YUITest.TestRunner._handleError(ex);\n                }\n\n                return result;\n            };\n        } else {\n\n            //method should fail if called when not expected\n            mock[name] = function(){\n                try {\n                    YUITest.Assert.fail(\"Method \" + name + \"() should not have been called.\");\n                } catch (ex){\n                    //route through TestRunner for proper handling\n                    YUITest.TestRunner._handleError(ex);\n                }\n            };\n        }\n    } else if (expectation.property){\n        //save expectations\n        mock.__expectations[name] = expectation;\n    }\n};\n\n/**\n * Verifies that all expectations of a mock object have been met and\n * throws an assertion error if not.\n * @param {Object} mock The object to verify..\n * @return {void}\n * @method verify\n * @static\n */\nYUITest.Mock.verify = function(mock){\n    try {\n\n        for (var name in mock.__expectations){\n            if (mock.__expectations.hasOwnProperty(name)){\n                var expectation = mock.__expectations[name];\n                if (expectation.method) {\n                    YUITest.Assert.areEqual(expectation.callCount, expectation.actualCallCount, \"Method \" + expectation.method + \"() wasn't called the expected number of times.\");\n                } else if (expectation.property){\n                    YUITest.Assert.areEqual(expectation.value, mock[expectation.property], \"Property \" + expectation.property + \" wasn't set to the correct value.\");\n                }\n            }\n        }\n\n    } catch (ex){\n        //route through TestRunner for proper handling\n        YUITest.TestRunner._handleError(ex);\n    }\n};\n\n/**\n * Creates a new value matcher.\n * @param {Function} method The function to call on the value.\n * @param {Array} originalArgs (Optional) Array of arguments to pass to the method.\n * @param {String} message (Optional) Message to display in case of failure.\n * @namespace YUITest.Mock\n * @class Value\n * @constructor\n */\nYUITest.Mock.Value = function(method, originalArgs, message){\n    if (this instanceof YUITest.Mock.Value){\n        this.verify = function(value){\n            var args = [].concat(originalArgs || []);\n            args.push(value);\n            args.push(message);\n            method.apply(null, args);\n        };\n    } else {\n        return new YUITest.Mock.Value(method, originalArgs, message);\n    }\n};\n\n/**\n * Predefined matcher to match any value.\n * @property Any\n * @static\n * @type Function\n */\nYUITest.Mock.Value.Any        = YUITest.Mock.Value(function(){});\n\n/**\n * Predefined matcher to match boolean values.\n * @property Boolean\n * @static\n * @type Function\n */\nYUITest.Mock.Value.Boolean    = YUITest.Mock.Value(YUITest.Assert.isBoolean);\n\n/**\n * Predefined matcher to match number values.\n * @property Number\n * @static\n * @type Function\n */\nYUITest.Mock.Value.Number     = YUITest.Mock.Value(YUITest.Assert.isNumber);\n\n/**\n * Predefined matcher to match string values.\n * @property String\n * @static\n * @type Function\n */\nYUITest.Mock.Value.String     = YUITest.Mock.Value(YUITest.Assert.isString);\n\n/**\n * Predefined matcher to match object values.\n * @property Object\n * @static\n * @type Function\n */\nYUITest.Mock.Value.Object     = YUITest.Mock.Value(YUITest.Assert.isObject);\n\n/**\n * Predefined matcher to match function values.\n * @property Function\n * @static\n * @type Function\n */\nYUITest.Mock.Value.Function   = YUITest.Mock.Value(YUITest.Assert.isFunction);\n\n/**\n * Convenience type for storing and aggregating\n * test result information.\n * @private\n * @namespace YUITest\n * @class Results\n * @constructor\n * @param {String} name The name of the test.\n */\nYUITest.Results = function(name){\n\n    /**\n     * Name of the test, test case, or test suite.\n     * @type String\n     * @property name\n     */\n    this.name = name;\n\n    /**\n     * Number of passed tests.\n     * @type int\n     * @property passed\n     */\n    this.passed = 0;\n\n    /**\n     * Number of failed tests.\n     * @type int\n     * @property failed\n     */\n    this.failed = 0;\n\n    /**\n     * Number of errors that occur in non-test methods.\n     * @type int\n     * @property errors\n     */\n    this.errors = 0;\n\n    /**\n     * Number of ignored tests.\n     * @type int\n     * @property ignored\n     */\n    this.ignored = 0;\n\n    /**\n     * Number of total tests.\n     * @type int\n     * @property total\n     */\n    this.total = 0;\n\n    /**\n     * Amount of time (ms) it took to complete testing.\n     * @type int\n     * @property duration\n     */\n    this.duration = 0;\n};\n\n/**\n * Includes results from another results object into this one.\n * @param {YUITest.Results} result The results object to include.\n * @method include\n * @return {void}\n */\nYUITest.Results.prototype.include = function(results){\n    this.passed += results.passed;\n    this.failed += results.failed;\n    this.ignored += results.ignored;\n    this.total += results.total;\n    this.errors += results.errors;\n};\n\n/**\n * Test case containing various tests to run.\n * @param template An object containing any number of test methods, other methods,\n *                 an optional name, and anything else the test case needs.\n * @class TestCase\n * @namespace YUITest\n * @constructor\n */\nYUITest.TestCase = function (template) {\n\n    /**\n     * Special rules for the test case. Possible subobjects\n     * are fail, for tests that should fail, and error, for\n     * tests that should throw an error.\n     */\n    this._should = {};\n\n    //copy over all properties from the template to this object\n    for (var prop in template) {\n        this[prop] = template[prop];\n    }\n\n    //check for a valid name\n    if (typeof this.name != \"string\"){\n        this.name = \"testCase\" + (+new Date());\n    }\n\n};\n\nYUITest.TestCase.prototype = {\n\n    //restore constructor\n    constructor: YUITest.TestCase,\n\n    /**\n     * Method to call from an async init method to\n     * restart the test case. When called, returns a function\n     * that should be called when tests are ready to continue.\n     * @method callback\n     * @return {Function} The function to call as a callback.\n     */\n    callback: function(){\n        return YUITest.TestRunner.callback.apply(YUITest.TestRunner,arguments);\n    },\n\n    /**\n     * Resumes a paused test and runs the given function.\n     * @param {Function} segment (Optional) The function to run.\n     *      If omitted, the test automatically passes.\n     * @return {Void}\n     * @method resume\n     */\n    resume : function (segment) {\n        YUITest.TestRunner.resume(segment);\n    },\n\n    /**\n     * Causes the test case to wait a specified amount of time and then\n     * continue executing the given code.\n     * @param {Function} segment (Optional) The function to run after the delay.\n     *      If omitted, the TestRunner will wait until resume() is called.\n     * @param {int} delay (Optional) The number of milliseconds to wait before running\n     *      the function. If omitted, defaults to zero.\n     * @return {Void}\n     * @method wait\n     */\n    wait : function (segment, delay){\n\n        var actualDelay = (typeof segment == \"number\" ? segment : delay);\n        actualDelay = (typeof actualDelay == \"number\" ? actualDelay : 10000);\n\n\t\tif (typeof segment == \"function\"){\n            throw new YUITest.Wait(segment, actualDelay);\n        } else {\n            throw new YUITest.Wait(function(){\n                YUITest.Assert.fail(\"Timeout: wait() called but resume() never called.\");\n            }, actualDelay);\n        }\n    },\n\n    //-------------------------------------------------------------------------\n    // Assertion Methods\n    //-------------------------------------------------------------------------\n\n    /**\n     * Asserts that a given condition is true. If not, then a YUITest.AssertionError object is thrown\n     * and the test fails.\n     * @method assert\n     * @param {Boolean} condition The condition to test.\n     * @param {String} message The message to display if the assertion fails.\n     */\n    assert : function (condition, message){\n        YUITest.Assert._increment();\n        if (!condition){\n            throw new YUITest.AssertionError(YUITest.Assert._formatMessage(message, \"Assertion failed.\"));\n        }\n    },\n\n    /**\n     * Forces an assertion error to occur. Shortcut for YUITest.Assert.fail().\n     * @method fail\n     * @param {String} message (Optional) The message to display with the failure.\n     */\n    fail: function (message) {\n        YUITest.Assert.fail(message);\n    },\n\n    //-------------------------------------------------------------------------\n    // Stub Methods\n    //-------------------------------------------------------------------------\n\n    /**\n     * Function to run once before tests start to run.\n     * This executes before the first call to setUp().\n     */\n    init: function(){\n        //noop\n    },\n\n    /**\n     * Function to run once after tests finish running.\n     * This executes after the last call to tearDown().\n     */\n    destroy: function(){\n        //noop\n    },\n\n    /**\n     * Function to run before each test is executed.\n     * @return {Void}\n     * @method setUp\n     */\n    setUp : function () {\n        //noop\n    },\n\n    /**\n     * Function to run after each test is executed.\n     * @return {Void}\n     * @method tearDown\n     */\n    tearDown: function () {\n        //noop\n    }\n};\n\n\n\n/**\n * A test suite that can contain a collection of TestCase and TestSuite objects.\n * @param {String||Object} data The name of the test suite or an object containing\n *      a name property as well as setUp and tearDown methods.\n * @namespace YUITest\n * @class TestSuite\n * @constructor\n */\nYUITest.TestSuite = function (data) {\n\n    /**\n     * The name of the test suite.\n     * @type String\n     * @property name\n     */\n    this.name = \"\";\n\n    /**\n     * Array of test suites and test cases.\n     * @type Array\n     * @property items\n     * @private\n     */\n    this.items = [];\n\n    //initialize the properties\n    if (typeof data == \"string\"){\n        this.name = data;\n    } else if (data instanceof Object){\n        for (var prop in data){\n            if (data.hasOwnProperty(prop)){\n                this[prop] = data[prop];\n            }\n        }\n    }\n\n    //double-check name\n    if (this.name === \"\"){\n        this.name = \"testSuite\" + (+new Date());\n    }\n\n};\n\nYUITest.TestSuite.prototype = {\n\n    //restore constructor\n    constructor: YUITest.TestSuite,\n\n    /**\n     * Adds a test suite or test case to the test suite.\n     * @param {YUITest.TestSuite||YUITest.TestCase} testObject The test suite or test case to add.\n     * @return {Void}\n     * @method add\n     */\n    add : function (testObject) {\n        if (testObject instanceof YUITest.TestSuite || testObject instanceof YUITest.TestCase) {\n            this.items.push(testObject);\n        }\n        return this;\n    },\n\n    //-------------------------------------------------------------------------\n    // Stub Methods\n    //-------------------------------------------------------------------------\n\n    /**\n     * Function to run before each test is executed.\n     * @return {Void}\n     * @method setUp\n     */\n    setUp : function () {\n    },\n\n    /**\n     * Function to run after each test is executed.\n     * @return {Void}\n     * @method tearDown\n     */\n    tearDown: function () {\n    }\n\n};\n\n/**\n * An object object containing test result formatting methods.\n * @namespace YUITest\n * @class TestFormat\n * @static\n */\nYUITest.TestFormat = function(){\n\n    /* (intentionally not documented)\n     * Basic XML escaping method. Replaces quotes, less-than, greater-than,\n     * apostrophe, and ampersand characters with their corresponding entities.\n     * @param {String} text The text to encode.\n     * @return {String} The XML-escaped text.\n     */\n    function xmlEscape(text){\n\n        return text.replace(/[<>\"'&]/g, function(value){\n            switch(value){\n                case \"<\":   return \"&lt;\";\n                case \">\":   return \"&gt;\";\n                case \"\\\"\":  return \"&quot;\";\n                case \"'\":   return \"&apos;\";\n                case \"&\":   return \"&amp;\";\n            }\n        });\n\n    }\n\n\n    return {\n\n        /**\n         * Returns test results formatted as a JSON string. Requires JSON utility.\n         * @param {Object} result The results object created by TestRunner.\n         * @return {String} A JSON-formatted string of results.\n         * @method JSON\n         * @static\n         */\n        JSON: function(results) {\n            return YUITest.Util.JSON.stringify(results);\n        },\n\n        /**\n         * Returns test results formatted as an XML string.\n         * @param {Object} result The results object created by TestRunner.\n         * @return {String} An XML-formatted string of results.\n         * @method XML\n         * @static\n         */\n        XML: function(results) {\n\n            function serializeToXML(results){\n                var xml = \"<\" + results.type + \" name=\\\"\" + xmlEscape(results.name) + \"\\\"\";\n\n                if (typeof(results.duration)==\"number\"){\n                    xml += \" duration=\\\"\" + results.duration + \"\\\"\";\n                }\n\n                if (results.type == \"test\"){\n                    xml += \" result=\\\"\" + results.result + \"\\\" message=\\\"\" + xmlEscape(results.message) + \"\\\">\";\n                } else {\n                    xml += \" passed=\\\"\" + results.passed + \"\\\" failed=\\\"\" + results.failed + \"\\\" ignored=\\\"\" + results.ignored + \"\\\" total=\\\"\" + results.total + \"\\\">\";\n                    for (var prop in results){\n                        if (results.hasOwnProperty(prop)){\n                            if (results[prop] && typeof results[prop] == \"object\" && !(results[prop] instanceof Array)){\n                                xml += serializeToXML(results[prop]);\n                            }\n                        }\n                    }\n                }\n\n                xml += \"</\" + results.type + \">\";\n\n                return xml;\n            }\n\n            return \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\" + serializeToXML(results);\n\n        },\n\n\n        /**\n         * Returns test results formatted in JUnit XML format.\n         * @param {Object} result The results object created by TestRunner.\n         * @return {String} An XML-formatted string of results.\n         * @method JUnitXML\n         * @static\n         */\n        JUnitXML: function(results) {\n\n            function serializeToJUnitXML(results){\n                var xml = \"\";\n\n                switch (results.type){\n                    //equivalent to testcase in JUnit\n                    case \"test\":\n                        if (results.result != \"ignore\"){\n                            xml = \"<testcase name=\\\"\" + xmlEscape(results.name) + \"\\\" time=\\\"\" + (results.duration/1000) + \"\\\">\";\n                            if (results.result == \"fail\"){\n                                xml += \"<failure message=\\\"\" + xmlEscape(results.message) + \"\\\"><![CDATA[\" + results.message + \"]]></failure>\";\n                            }\n                            xml+= \"</testcase>\";\n                        }\n                        break;\n\n                    //equivalent to testsuite in JUnit\n                    case \"testcase\":\n\n                        xml = \"<testsuite name=\\\"\" + xmlEscape(results.name) + \"\\\" tests=\\\"\" + results.total + \"\\\" failures=\\\"\" + results.failed + \"\\\" time=\\\"\" + (results.duration/1000) + \"\\\">\";\n\n                        for (var prop in results){\n                            if (results.hasOwnProperty(prop)){\n                                if (results[prop] && typeof results[prop] == \"object\" && !(results[prop] instanceof Array)){\n                                    xml += serializeToJUnitXML(results[prop]);\n                                }\n                            }\n                        }\n\n                        xml += \"</testsuite>\";\n                        break;\n\n                    //no JUnit equivalent, don't output anything\n                    case \"testsuite\":\n                        for (var prop in results){\n                            if (results.hasOwnProperty(prop)){\n                                if (results[prop] && typeof results[prop] == \"object\" && !(results[prop] instanceof Array)){\n                                    xml += serializeToJUnitXML(results[prop]);\n                                }\n                            }\n                        }\n                        break;\n\n                    //top-level, equivalent to testsuites in JUnit\n                    case \"report\":\n\n                        xml = \"<testsuites>\";\n\n                        for (var prop in results){\n                            if (results.hasOwnProperty(prop)){\n                                if (results[prop] && typeof results[prop] == \"object\" && !(results[prop] instanceof Array)){\n                                    xml += serializeToJUnitXML(results[prop]);\n                                }\n                            }\n                        }\n\n                        xml += \"</testsuites>\";\n\n                    //no default\n                }\n\n                return xml;\n\n            }\n\n            return \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\" + serializeToJUnitXML(results);\n        },\n\n        /**\n         * Returns test results formatted in TAP format.\n         * For more information, see <a href=\"http://testanything.org/\">Test Anything Protocol</a>.\n         * @param {Object} result The results object created by TestRunner.\n         * @return {String} A TAP-formatted string of results.\n         * @method TAP\n         * @static\n         */\n        TAP: function(results) {\n\n            var currentTestNum = 1;\n\n            function serializeToTAP(results){\n                var text = \"\";\n\n                switch (results.type){\n\n                    case \"test\":\n                        if (results.result != \"ignore\"){\n\n                            text = \"ok \" + (currentTestNum++) + \" - \" + results.name;\n\n                            if (results.result == \"fail\"){\n                                text = \"not \" + text + \" - \" + results.message;\n                            }\n\n                            text += \"\\n\";\n                        } else {\n                            text = \"#Ignored test \" + results.name + \"\\n\";\n                        }\n                        break;\n\n                    case \"testcase\":\n\n                        text = \"#Begin testcase \" + results.name + \"(\" + results.failed + \" failed of \" + results.total + \")\\n\";\n\n                        for (var prop in results){\n                            if (results.hasOwnProperty(prop)){\n                                if (results[prop] && typeof results[prop] == \"object\" && !(results[prop] instanceof Array)){\n                                    text += serializeToTAP(results[prop]);\n                                }\n                            }\n                        }\n\n                        text += \"#End testcase \" + results.name + \"\\n\";\n\n\n                        break;\n\n                    case \"testsuite\":\n\n                        text = \"#Begin testsuite \" + results.name + \"(\" + results.failed + \" failed of \" + results.total + \")\\n\";\n\n                        for (var prop in results){\n                            if (results.hasOwnProperty(prop)){\n                                if (results[prop] && typeof results[prop] == \"object\" && !(results[prop] instanceof Array)){\n                                    text += serializeToTAP(results[prop]);\n                                }\n                            }\n                        }\n\n                        text += \"#End testsuite \" + results.name + \"\\n\";\n                        break;\n\n                    case \"report\":\n\n                        for (var prop in results){\n                            if (results.hasOwnProperty(prop)){\n                                if (results[prop] && typeof results[prop] == \"object\" && !(results[prop] instanceof Array)){\n                                    text += serializeToTAP(results[prop]);\n                                }\n                            }\n                        }\n\n                    //no default\n                }\n\n                return text;\n\n            }\n\n            return \"1..\" + results.total + \"\\n\" + serializeToTAP(results);\n        }\n\n    };\n}();\n\n/**\n * An object object containing coverage result formatting methods.\n * @namespace YUITest\n * @class CoverageFormat\n * @static\n */\nYUITest.CoverageFormat = {\n\n    /**\n     * Returns the coverage report in JSON format. This is the straight\n     * JSON representation of the native coverage report.\n     * @param {Object} coverage The coverage report object.\n     * @return {String} A JSON-formatted string of coverage data.\n     * @method JSON\n     * @namespace YUITest.CoverageFormat\n     */\n    JSON: function(coverage){\n        return YUITest.Util.JSON.stringify(coverage);\n    },\n\n    /**\n     * Returns the coverage report in a JSON format compatible with\n     * Xdebug. See <a href=\"http://www.xdebug.com/docs/code_coverage\">Xdebug Documentation</a>\n     * for more information. Note: function coverage is not available\n     * in this format.\n     * @param {Object} coverage The coverage report object.\n     * @return {String} A JSON-formatted string of coverage data.\n     * @method XdebugJSON\n     * @namespace YUITest.CoverageFormat\n     */\n    XdebugJSON: function(coverage){\n\n        var report = {};\n        for (var prop in coverage){\n            if (coverage.hasOwnProperty(prop)){\n                report[prop] = coverage[prop].lines;\n            }\n        }\n\n        return YUITest.Util.JSON.stringify(coverage);\n    }\n\n};\n\n\n/**\n * An object object containing methods to simulate browser events.\n * @namespace YUITest\n * @class Event\n * @static\n */\nYUITest.Event = (function() {\n\n    var\n\n    //mouse events supported\n    mouseEvents = {\n        click:      1,\n        dblclick:   1,\n        mouseover:  1,\n        mouseout:   1,\n        mousedown:  1,\n        mouseup:    1,\n        mousemove:  1\n    },\n\n    //key events supported\n    keyEvents   = {\n        keydown:    1,\n        keyup:      1,\n        keypress:   1\n    },\n\n    //HTML events supported\n    uiEvents  = {\n        blur:       1,\n        change:     1,\n        focus:      1,\n        resize:     1,\n        scroll:     1,\n        select:     1\n    },\n\n    //events that bubble by default\n    bubbleEvents = {\n        scroll:     1,\n        resize:     1,\n        reset:      1,\n        submit:     1,\n        change:     1,\n        select:     1,\n        error:      1,\n        abort:      1,\n\n        //also mouse events\n        click:      1,\n        dblclick:   1,\n        mouseover:  1,\n        mouseout:   1,\n        mousedown:  1,\n        mouseup:    1,\n        mousemove:  1,\n\n        //and keyboard events\n        keydown:    1,\n        keyup:      1,\n        keypress:   1\n\n    },\n\n    //the object to return\n    object,\n\n    //used for property name iteration\n    prop;\n\n    /*\n     * Note: Intentionally not for YUIDoc generation.\n     * Simulates a key event using the given event information to populate\n     * the generated event object. This method does browser-equalizing\n     * calculations to account for differences in the DOM and IE event models\n     * as well as different browser quirks. Note: keydown causes Safari 2.x to\n     * crash.\n     * @method simulateKeyEvent\n     * @private\n     * @static\n     * @param {HTMLElement} target The target of the given event.\n     * @param {String} type The type of event to fire. This can be any one of\n     *      the following: keyup, keydown, and keypress.\n     * @param {Boolean} bubbles (Optional) Indicates if the event can be\n     *      bubbled up. DOM Level 3 specifies that all key events bubble by\n     *      default. The default is true.\n     * @param {Boolean} cancelable (Optional) Indicates if the event can be\n     *      canceled using preventDefault(). DOM Level 3 specifies that all\n     *      key events can be cancelled. The default\n     *      is true.\n     * @param {Window} view (Optional) The view containing the target. This is\n     *      typically the window object. The default is window.\n     * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys\n     *      is pressed while the event is firing. The default is false.\n     * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys\n     *      is pressed while the event is firing. The default is false.\n     * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys\n     *      is pressed while the event is firing. The default is false.\n     * @param {Boolean} metaKey (Optional) Indicates if one of the META keys\n     *      is pressed while the event is firing. The default is false.\n     * @param {int} keyCode (Optional) The code for the key that is in use.\n     *      The default is 0.\n     * @param {int} charCode (Optional) The Unicode code for the character\n     *      associated with the key being used. The default is 0.\n     */\n    function simulateKeyEvent(target /*:HTMLElement*/, type /*:String*/,\n                                 bubbles /*:Boolean*/,  cancelable /*:Boolean*/,\n                                 view /*:Window*/,\n                                 ctrlKey /*:Boolean*/,    altKey /*:Boolean*/,\n                                 shiftKey /*:Boolean*/,   metaKey /*:Boolean*/,\n                                 keyCode /*:int*/,        charCode /*:int*/) /*:Void*/\n    {\n        //check target\n        if (!target){\n            throw new Error(\"simulateKeyEvent(): Invalid target.\");\n        }\n\n        //check event type\n        if (typeof type == \"string\"){\n            type = type.toLowerCase();\n            switch(type){\n                case \"textevent\": //DOM Level 3\n                    type = \"keypress\";\n                    break;\n                case \"keyup\":\n                case \"keydown\":\n                case \"keypress\":\n                    break;\n                default:\n                    throw new Error(\"simulateKeyEvent(): Event type '\" + type + \"' not supported.\");\n            }\n        } else {\n            throw new Error(\"simulateKeyEvent(): Event type must be a string.\");\n        }\n\n        //setup default values\n        if (typeof bubbles != \"boolean\"){\n            bubbles = true; //all key events bubble\n        }\n        if (typeof cancelable != \"boolean\"){\n            cancelable = true; //all key events can be cancelled\n        }\n        if (typeof view != \"object\" || view == null){\n            view = window; //view is typically window\n        }\n        if (typeof ctrlKey != \"boolean\"){\n            ctrlKey = false;\n        }\n        if (typeof altKey != \"boolean\"){\n            altKey = false;\n        }\n        if (typeof shiftKey != \"boolean\"){\n            shiftKey = false;\n        }\n        if (typeof metaKey != \"boolean\"){\n            metaKey = false;\n        }\n        if (typeof keyCode != \"number\"){\n            keyCode = 0;\n        }\n        if (typeof charCode != \"number\"){\n            charCode = 0;\n        }\n\n        //try to create a mouse event\n        var customEvent = null;\n\n        //check for DOM-compliant browsers first\n        if (typeof document.createEvent == \"function\"){\n\n            try {\n\n                //try to create key event\n                customEvent = document.createEvent(\"KeyEvents\");\n\n                /*\n                 * Interesting problem: Firefox implemented a non-standard\n                 * version of initKeyEvent() based on DOM Level 2 specs.\n                 * Key event was removed from DOM Level 2 and re-introduced\n                 * in DOM Level 3 with a different interface. Firefox is the\n                 * only browser with any implementation of Key Events, so for\n                 * now, assume it's Firefox if the above line doesn't error.\n                 */\n                // @TODO: Decipher between Firefox's implementation and a correct one.\n                customEvent.initKeyEvent(type, bubbles, cancelable, view, ctrlKey,\n                    altKey, shiftKey, metaKey, keyCode, charCode);\n\n            } catch (ex){\n\n                /*\n                 * If it got here, that means key events aren't officially supported.\n                 * Safari/WebKit is a real problem now. WebKit 522 won't let you\n                 * set keyCode, charCode, or other properties if you use a\n                 * UIEvent, so we first must try to create a generic event. The\n                 * fun part is that this will throw an error on Safari 2.x. The\n                 * end result is that we need another try...catch statement just to\n                 * deal with this mess.\n                 */\n                try {\n\n                    //try to create generic event - will fail in Safari 2.x\n                    customEvent = document.createEvent(\"Events\");\n\n                } catch (uierror /*:Error*/){\n\n                    //the above failed, so create a UIEvent for Safari 2.x\n                    customEvent = document.createEvent(\"UIEvents\");\n\n                } finally {\n\n                    customEvent.initEvent(type, bubbles, cancelable);\n\n                    //initialize\n                    customEvent.view = view;\n                    customEvent.altKey = altKey;\n                    customEvent.ctrlKey = ctrlKey;\n                    customEvent.shiftKey = shiftKey;\n                    customEvent.metaKey = metaKey;\n                    customEvent.keyCode = keyCode;\n                    customEvent.charCode = charCode;\n\n                }\n\n            }\n\n            //fire the event\n            target.dispatchEvent(customEvent);\n\n        } else if (typeof document.createEventObject != \"undefined\"){ //IE\n\n            //create an IE event object\n            customEvent = document.createEventObject();\n\n            //assign available properties\n            customEvent.bubbles = bubbles;\n            customEvent.cancelable = cancelable;\n            customEvent.view = view;\n            customEvent.ctrlKey = ctrlKey;\n            customEvent.altKey = altKey;\n            customEvent.shiftKey = shiftKey;\n            customEvent.metaKey = metaKey;\n\n            /*\n             * IE doesn't support charCode explicitly. CharCode should\n             * take precedence over any keyCode value for accurate\n             * representation.\n             */\n            customEvent.keyCode = (charCode > 0) ? charCode : keyCode;\n\n            //fire the event\n            target.fireEvent(\"on\" + type, customEvent);\n\n        } else {\n            throw new Error(\"simulateKeyEvent(): No event simulation framework present.\");\n        }\n    }\n\n    /*\n     * Note: Intentionally not for YUIDoc generation.\n     * Simulates a mouse event using the given event information to populate\n     * the generated event object. This method does browser-equalizing\n     * calculations to account for differences in the DOM and IE event models\n     * as well as different browser quirks.\n     * @method simulateMouseEvent\n     * @private\n     * @static\n     * @param {HTMLElement} target The target of the given event.\n     * @param {String} type The type of event to fire. This can be any one of\n     *      the following: click, dblclick, mousedown, mouseup, mouseout,\n     *      mouseover, and mousemove.\n     * @param {Boolean} bubbles (Optional) Indicates if the event can be\n     *      bubbled up. DOM Level 2 specifies that all mouse events bubble by\n     *      default. The default is true.\n     * @param {Boolean} cancelable (Optional) Indicates if the event can be\n     *      canceled using preventDefault(). DOM Level 2 specifies that all\n     *      mouse events except mousemove can be cancelled. The default\n     *      is true for all events except mousemove, for which the default\n     *      is false.\n     * @param {Window} view (Optional) The view containing the target. This is\n     *      typically the window object. The default is window.\n     * @param {int} detail (Optional) The number of times the mouse button has\n     *      been used. The default value is 1.\n     * @param {int} screenX (Optional) The x-coordinate on the screen at which\n     *      point the event occured. The default is 0.\n     * @param {int} screenY (Optional) The y-coordinate on the screen at which\n     *      point the event occured. The default is 0.\n     * @param {int} clientX (Optional) The x-coordinate on the client at which\n     *      point the event occured. The default is 0.\n     * @param {int} clientY (Optional) The y-coordinate on the client at which\n     *      point the event occured. The default is 0.\n     * @param {Boolean} ctrlKey (Optional) Indicates if one of the CTRL keys\n     *      is pressed while the event is firing. The default is false.\n     * @param {Boolean} altKey (Optional) Indicates if one of the ALT keys\n     *      is pressed while the event is firing. The default is false.\n     * @param {Boolean} shiftKey (Optional) Indicates if one of the SHIFT keys\n     *      is pressed while the event is firing. The default is false.\n     * @param {Boolean} metaKey (Optional) Indicates if one of the META keys\n     *      is pressed while the event is firing. The default is false.\n     * @param {int} button (Optional) The button being pressed while the event\n     *      is executing. The value should be 0 for the primary mouse button\n     *      (typically the left button), 1 for the terciary mouse button\n     *      (typically the middle button), and 2 for the secondary mouse button\n     *      (typically the right button). The default is 0.\n     * @param {HTMLElement} relatedTarget (Optional) For mouseout events,\n     *      this is the element that the mouse has moved to. For mouseover\n     *      events, this is the element that the mouse has moved from. This\n     *      argument is ignored for all other events. The default is null.\n     */\n    function simulateMouseEvent(target /*:HTMLElement*/, type /*:String*/,\n                                   bubbles /*:Boolean*/,  cancelable /*:Boolean*/,\n                                   view /*:Window*/,        detail /*:int*/,\n                                   screenX /*:int*/,        screenY /*:int*/,\n                                   clientX /*:int*/,        clientY /*:int*/,\n                                   ctrlKey /*:Boolean*/,    altKey /*:Boolean*/,\n                                   shiftKey /*:Boolean*/,   metaKey /*:Boolean*/,\n                                   button /*:int*/,         relatedTarget /*:HTMLElement*/) /*:Void*/\n    {\n\n        //check target\n        if (!target){\n            throw new Error(\"simulateMouseEvent(): Invalid target.\");\n        }\n\n        //check event type\n        if (typeof type == \"string\"){\n            type = type.toLowerCase();\n\n            //make sure it's a supported mouse event\n            if (!mouseEvents[type]){\n                throw new Error(\"simulateMouseEvent(): Event type '\" + type + \"' not supported.\");\n            }\n        } else {\n            throw new Error(\"simulateMouseEvent(): Event type must be a string.\");\n        }\n\n        //setup default values\n        if (typeof bubbles != \"boolean\"){\n            bubbles = true; //all mouse events bubble\n        }\n        if (typeof cancelable != \"boolean\"){\n            cancelable = (type != \"mousemove\"); //mousemove is the only one that can't be cancelled\n        }\n        if (typeof view != \"object\" || view != null){\n            view = window; //view is typically window\n        }\n        if (typeof detail != \"number\"){\n            detail = 1;  //number of mouse clicks must be at least one\n        }\n        if (typeof screenX != \"number\"){\n            screenX = 0;\n        }\n        if (typeof screenY != \"number\"){\n            screenY = 0;\n        }\n        if (typeof clientX != \"number\"){\n            clientX = 0;\n        }\n        if (typeof clientY != \"number\"){\n            clientY = 0;\n        }\n        if (typeof ctrlKey != \"boolean\"){\n            ctrlKey = false;\n        }\n        if (typeof altKey != \"boolean\"){\n            altKey = false;\n        }\n        if (typeof shiftKey != \"boolean\"){\n            shiftKey = false;\n        }\n        if (typeof metaKey != \"boolean\"){\n            metaKey = false;\n        }\n        if (typeof button != \"number\"){\n            button = 0;\n        }\n\n        if (!relatedTarget){\n            relatedTarget = null;\n        }\n\n        //try to create a mouse event\n        var customEvent /*:MouseEvent*/ = null;\n\n        //check for DOM-compliant browsers first\n        if (typeof document.createEvent == \"function\"){\n\n            customEvent = document.createEvent(\"MouseEvents\");\n\n            //Safari 2.x (WebKit 418) still doesn't implement initMouseEvent()\n            if (customEvent.initMouseEvent){\n                customEvent.initMouseEvent(type, bubbles, cancelable, view, detail,\n                                     screenX, screenY, clientX, clientY,\n                                     ctrlKey, altKey, shiftKey, metaKey,\n                                     button, relatedTarget);\n            } else { //Safari\n\n                //the closest thing available in Safari 2.x is UIEvents\n                customEvent = document.createEvent(\"UIEvents\");\n                customEvent.initEvent(type, bubbles, cancelable);\n                customEvent.view = view;\n                customEvent.detail = detail;\n                customEvent.screenX = screenX;\n                customEvent.screenY = screenY;\n                customEvent.clientX = clientX;\n                customEvent.clientY = clientY;\n                customEvent.ctrlKey = ctrlKey;\n                customEvent.altKey = altKey;\n                customEvent.metaKey = metaKey;\n                customEvent.shiftKey = shiftKey;\n                customEvent.button = button;\n                customEvent.relatedTarget = relatedTarget;\n            }\n\n            /*\n             * Check to see if relatedTarget has been assigned. Firefox\n             * versions less than 2.0 don't allow it to be assigned via\n             * initMouseEvent() and the property is readonly after event\n             * creation, so in order to keep YAHOO.util.getRelatedTarget()\n             * working, assign to the IE proprietary toElement property\n             * for mouseout event and fromElement property for mouseover\n             * event.\n             */\n            if (relatedTarget && !customEvent.relatedTarget){\n                if (type == \"mouseout\"){\n                    customEvent.toElement = relatedTarget;\n                } else if (type == \"mouseover\"){\n                    customEvent.fromElement = relatedTarget;\n                }\n            }\n\n            //fire the event\n            target.dispatchEvent(customEvent);\n\n        } else if (typeof document.createEventObject != \"undefined\"){ //IE\n\n            //create an IE event object\n            customEvent = document.createEventObject();\n\n            //assign available properties\n            customEvent.bubbles = bubbles;\n            customEvent.cancelable = cancelable;\n            customEvent.view = view;\n            customEvent.detail = detail;\n            customEvent.screenX = screenX;\n            customEvent.screenY = screenY;\n            customEvent.clientX = clientX;\n            customEvent.clientY = clientY;\n            customEvent.ctrlKey = ctrlKey;\n            customEvent.altKey = altKey;\n            customEvent.metaKey = metaKey;\n            customEvent.shiftKey = shiftKey;\n\n            //fix button property for IE's wacky implementation\n            switch(button){\n                case 0:\n                    customEvent.button = 1;\n                    break;\n                case 1:\n                    customEvent.button = 4;\n                    break;\n                case 2:\n                    //leave as is\n                    break;\n                default:\n                    customEvent.button = 0;\n            }\n\n            /*\n             * Have to use relatedTarget because IE won't allow assignment\n             * to toElement or fromElement on generic events. This keeps\n             * YAHOO.util.customEvent.getRelatedTarget() functional.\n             */\n            customEvent.relatedTarget = relatedTarget;\n\n            //fire the event\n            target.fireEvent(\"on\" + type, customEvent);\n\n        } else {\n            throw new Error(\"simulateMouseEvent(): No event simulation framework present.\");\n        }\n    }\n\n    /*\n     * Note: Intentionally not for YUIDoc generation.\n     * Simulates a UI event using the given event information to populate\n     * the generated event object. This method does browser-equalizing\n     * calculations to account for differences in the DOM and IE event models\n     * as well as different browser quirks.\n     * @method simulateHTMLEvent\n     * @private\n     * @static\n     * @param {HTMLElement} target The target of the given event.\n     * @param {String} type The type of event to fire. This can be any one of\n     *      the following: click, dblclick, mousedown, mouseup, mouseout,\n     *      mouseover, and mousemove.\n     * @param {Boolean} bubbles (Optional) Indicates if the event can be\n     *      bubbled up. DOM Level 2 specifies that all mouse events bubble by\n     *      default. The default is true.\n     * @param {Boolean} cancelable (Optional) Indicates if the event can be\n     *      canceled using preventDefault(). DOM Level 2 specifies that all\n     *      mouse events except mousemove can be cancelled. The default\n     *      is true for all events except mousemove, for which the default\n     *      is false.\n     * @param {Window} view (Optional) The view containing the target. This is\n     *      typically the window object. The default is window.\n     * @param {int} detail (Optional) The number of times the mouse button has\n     *      been used. The default value is 1.\n     */\n    function simulateUIEvent(target /*:HTMLElement*/, type /*:String*/,\n                                   bubbles /*:Boolean*/,  cancelable /*:Boolean*/,\n                                   view /*:Window*/,        detail /*:int*/) /*:Void*/\n    {\n\n        //check target\n        if (!target){\n            throw new Error(\"simulateUIEvent(): Invalid target.\");\n        }\n\n        //check event type\n        if (typeof type == \"string\"){\n            type = type.toLowerCase();\n\n            //make sure it's a supported mouse event\n            if (!uiEvents[type]){\n                throw new Error(\"simulateUIEvent(): Event type '\" + type + \"' not supported.\");\n            }\n        } else {\n            throw new Error(\"simulateUIEvent(): Event type must be a string.\");\n        }\n\n        //try to create a mouse event\n        var customEvent = null;\n\n\n        //setup default values\n        if (typeof bubbles != \"boolean\"){\n            bubbles = (type in bubbleEvents);  //not all events bubble\n        }\n        if (typeof cancelable != \"boolean\"){\n            cancelable = (type == \"submit\"); //submit is the only one that can be cancelled\n        }\n        if (typeof view != \"object\" || view != null){\n            view = window; //view is typically window\n        }\n        if (typeof detail != \"number\"){\n            detail = 1;  //usually not used but defaulted to this\n        }\n\n        //check for DOM-compliant browsers first\n        if (typeof document.createEvent == \"function\"){\n\n            //just a generic UI Event object is needed\n            customEvent = document.createEvent(\"UIEvents\");\n            customEvent.initUIEvent(type, bubbles, cancelable, view, detail);\n\n            //fire the event\n            target.dispatchEvent(customEvent);\n\n        } else if (typeof document.createEventObject != \"undefined\"){ //IE\n\n            //create an IE event object\n            customEvent = document.createEventObject();\n\n            //assign available properties\n            customEvent.bubbles = bubbles;\n            customEvent.cancelable = cancelable;\n            customEvent.view = view;\n            customEvent.detail = detail;\n\n            //fire the event\n            target.fireEvent(\"on\" + type, customEvent);\n\n        } else {\n            throw new Error(\"simulateUIEvent(): No event simulation framework present.\");\n        }\n    }\n\n\n    /**\n     * Allows event simulation for browser-based events.\n     * @namespace YUITest\n     * @class Event\n     * @static\n     */\n    object = {\n\n        /**\n         * Simulates the event with the given name on a target.\n         * @param {HTMLElement} target The DOM element that's the target of the event.\n         * @param {String} type The type of event to simulate (i.e., \"click\").\n         * @param {Object} options (Optional) Extra options to copy onto the event object.\n         * @return {void}\n         * @method simulate\n         * @static\n         * @deprecated\n         */\n        simulate: function(target, type, options){\n\n            options = options || {};\n\n            if (mouseEvents[type]){\n                simulateMouseEvent(target, type, options.bubbles,\n                    options.cancelable, options.view, options.detail, options.screenX,\n                    options.screenY, options.clientX, options.clientY, options.ctrlKey,\n                    options.altKey, options.shiftKey, options.metaKey, options.button,\n                    options.relatedTarget);\n            } else if (keyEvents[type]){\n                simulateKeyEvent(target, type, options.bubbles,\n                    options.cancelable, options.view, options.ctrlKey,\n                    options.altKey, options.shiftKey, options.metaKey,\n                    options.keyCode, options.charCode);\n            } else if (uiEvents[type]){\n                simulateUIEvent(target, type, options.bubbles,\n                    options.cancelable, options.view, options.detail);\n             } else {\n                throw new Error(\"simulate(): Event '\" + type + \"' can't be simulated.\");\n            }\n        }\n    };\n\n    //create the convenience methods for mouse events\n    for (prop in mouseEvents){\n        if (mouseEvents.hasOwnProperty(prop)){\n            object[prop] = (function(type){\n                return function(target, options){\n                    options = options || {};\n                    simulateMouseEvent(target, type, options.bubbles,\n                        options.cancelable, options.view, options.detail, options.screenX,\n                        options.screenY, options.clientX, options.clientY, options.ctrlKey,\n                        options.altKey, options.shiftKey, options.metaKey, options.button,\n                        options.relatedTarget);\n                };\n            })(prop);\n        }\n    }\n\n    //create the convenience methods for key events\n    for (prop in keyEvents){\n        if (keyEvents.hasOwnProperty(prop)){\n            object[prop] = (function(type){\n                return function(target, options){\n                    options = options || {};\n                    simulateKeyEvent(target, type, options.bubbles,\n                        options.cancelable, options.view, options.ctrlKey,\n                        options.altKey, options.shiftKey, options.metaKey,\n                        options.keyCode, options.charCode);\n                };\n            })(prop);\n        }\n    }\n\n    //create the convenience methods for key events\n    for (prop in uiEvents){\n        if (uiEvents.hasOwnProperty(prop)){\n            object[prop] = (function(type){\n                return function(target, options){\n                    options = options || {};\n                    simulateUIEvent(target, type, options.bubbles,\n                        options.cancelable, options.view, options.detail);\n                };\n            })(prop);\n        }\n    }\n\n    return object;\n\n})();\n\n\n    /**\n     * An object capable of sending test results to a server.\n     * @param {String} url The URL to submit the results to.\n     * @param {Function} format (Optiona) A function that outputs the results in a specific format.\n     *      Default is YUITest.TestFormat.XML.\n     * @constructor\n     * @namespace YUITest\n     * @class Reporter\n     */\n    YUITest.Reporter = function(url, format) {\n\n        /**\n         * The URL to submit the data to.\n         * @type String\n         * @property url\n         */\n        this.url = url;\n\n        /**\n         * The formatting function to call when submitting the data.\n         * @type Function\n         * @property format\n         */\n        this.format = format || YUITest.TestFormat.XML;\n\n        /**\n         * Extra fields to submit with the request.\n         * @type Object\n         * @property _fields\n         * @private\n         */\n        this._fields = new Object();\n\n        /**\n         * The form element used to submit the results.\n         * @type HTMLFormElement\n         * @property _form\n         * @private\n         */\n        this._form = null;\n\n        /**\n         * Iframe used as a target for form submission.\n         * @type HTMLIFrameElement\n         * @property _iframe\n         * @private\n         */\n        this._iframe = null;\n    };\n\n    YUITest.Reporter.prototype = {\n\n        //restore missing constructor\n        constructor: YUITest.Reporter,\n\n        /**\n         * Adds a field to the form that submits the results.\n         * @param {String} name The name of the field.\n         * @param {Variant} value The value of the field.\n         * @return {Void}\n         * @method addField\n         */\n        addField : function (name, value){\n            this._fields[name] = value;\n        },\n\n        /**\n         * Removes all previous defined fields.\n         * @return {Void}\n         * @method addField\n         */\n        clearFields : function(){\n            this._fields = new Object();\n        },\n\n        /**\n         * Cleans up the memory associated with the TestReporter, removing DOM elements\n         * that were created.\n         * @return {Void}\n         * @method destroy\n         */\n        destroy : function() {\n            if (this._form){\n                this._form.parentNode.removeChild(this._form);\n                this._form = null;\n            }\n            if (this._iframe){\n                this._iframe.parentNode.removeChild(this._iframe);\n                this._iframe = null;\n            }\n            this._fields = null;\n        },\n\n        /**\n         * Sends the report to the server.\n         * @param {Object} results The results object created by TestRunner.\n         * @return {Void}\n         * @method report\n         */\n        report : function(results){\n\n            //if the form hasn't been created yet, create it\n            if (!this._form){\n                this._form = document.createElement(\"form\");\n                this._form.method = \"post\";\n                this._form.style.visibility = \"hidden\";\n                this._form.style.position = \"absolute\";\n                this._form.style.top = 0;\n                document.body.appendChild(this._form);\n\n                //IE won't let you assign a name using the DOM, must do it the hacky way\n                try {\n                    this._iframe = document.createElement(\"<iframe name=\\\"yuiTestTarget\\\" />\");\n                } catch (ex){\n                    this._iframe = document.createElement(\"iframe\");\n                    this._iframe.name = \"yuiTestTarget\";\n                }\n\n                this._iframe.src = \"javascript:false\";\n                this._iframe.style.visibility = \"hidden\";\n                this._iframe.style.position = \"absolute\";\n                this._iframe.style.top = 0;\n                document.body.appendChild(this._iframe);\n\n                this._form.target = \"yuiTestTarget\";\n            }\n\n            //set the form's action\n            this._form.action = this.url;\n\n            //remove any existing fields\n            while(this._form.hasChildNodes()){\n                this._form.removeChild(this._form.lastChild);\n            }\n\n            //create default fields\n            this._fields.results = this.format(results);\n            this._fields.useragent = navigator.userAgent;\n            this._fields.timestamp = (new Date()).toLocaleString();\n\n            //add fields to the form\n            for (var prop in this._fields){\n                var value = this._fields[prop];\n                if (this._fields.hasOwnProperty(prop) && (typeof value != \"function\")){\n                    var input = document.createElement(\"input\");\n                    input.type = \"hidden\";\n                    input.name = prop;\n                    input.value = value;\n                    this._form.appendChild(input);\n                }\n            }\n\n            //remove default fields\n            delete this._fields.results;\n            delete this._fields.useragent;\n            delete this._fields.timestamp;\n\n            if (arguments[1] !== false){\n                this._form.submit();\n            }\n\n        }\n\n    };\n\n\n/**\n * Runs pages containing test suite definitions.\n * @namespace YUITest\n * @class PageManager\n * @static\n */\nYUITest.PageManager = YUITest.Util.mix(new YUITest.EventTarget(), {\n\n    /**\n     * Constant for the testpagebegin custom event\n     * @property TEST_PAGE_BEGIN_EVENT\n     * @static\n     * @type string\n     * @final\n     */\n    TEST_PAGE_BEGIN_EVENT /*:String*/ : \"testpagebegin\",\n\n    /**\n     * Constant for the testpagecomplete custom event\n     * @property TEST_PAGE_COMPLETE_EVENT\n     * @static\n     * @type string\n     * @final\n     */\n    TEST_PAGE_COMPLETE_EVENT /*:String*/ : \"testpagecomplete\",\n\n    /**\n     * Constant for the testmanagerbegin custom event\n     * @property TEST_MANAGER_BEGIN_EVENT\n     * @static\n     * @type string\n     * @final\n     */\n    TEST_MANAGER_BEGIN_EVENT /*:String*/ : \"testmanagerbegin\",\n\n    /**\n     * Constant for the testmanagercomplete custom event\n     * @property TEST_MANAGER_COMPLETE_EVENT\n     * @static\n     * @type string\n     * @final\n     */\n    TEST_MANAGER_COMPLETE_EVENT /*:String*/ : \"testmanagercomplete\",\n\n    //-------------------------------------------------------------------------\n    // Private Properties\n    //-------------------------------------------------------------------------\n\n\n    /**\n     * The URL of the page currently being executed.\n     * @type String\n     * @private\n     * @property _curPage\n     * @static\n     */\n    _curPage: null,\n\n    /**\n     * The frame used to load and run tests.\n     * @type Window\n     * @private\n     * @property _frame\n     * @static\n     */\n    _frame: null,\n\n    /**\n     * The timeout ID for the next iteration through the tests.\n     * @type int\n     * @private\n     * @property _timeoutId\n     * @static\n     */\n    _timeoutId: 0,\n\n    /**\n     * Array of pages to load.\n     * @type String[]\n     * @private\n     * @property _pages\n     * @static\n     */\n    _pages: [],\n\n    /**\n     * Aggregated results\n     * @type Object\n     * @private\n     * @property _results\n     * @static\n     */\n    _results: null,\n\n    //-------------------------------------------------------------------------\n    // Private Methods\n    //-------------------------------------------------------------------------\n\n    /**\n     * Handles TestRunner.COMPLETE_EVENT, storing the results and beginning\n     * the loop again.\n     * @param {Object} data Data about the event.\n     * @return {Void}\n     * @method _handleTestRunnerComplete\n     * @private\n     * @static\n     */\n    _handleTestRunnerComplete : function (data /*:Object*/) /*:Void*/ {\n\n        this.fire(this.TEST_PAGE_COMPLETE_EVENT, {\n            page: this._curPage,\n            results: data.results\n        });\n\n        //save results\n        //this._results[this.curPage] = data.results;\n\n        //process 'em\n        this._processResults(this._curPage, data.results);\n\n\n        //if there's more to do, set a timeout to begin again\n        if (this._pages.length){\n            this._timeoutId = setTimeout(function(){\n                YUITest.TestManager._run();\n            }, 1000);\n        } else {\n            this.fire(this.TEST_MANAGER_COMPLETE_EVENT, this._results);\n        }\n    },\n\n    /**\n     * Processes the results of a test page run, outputting log messages\n     * for failed tests.\n     * @return {Void}\n     * @method _processResults\n     * @private\n     * @static\n     */\n    _processResults : function (page, results){\n\n        var r = this._results;\n\n        r.passed += results.passed;\n        r.failed += results.failed;\n        r.ignored += results.ignored;\n        r.total += results.total;\n        r.duration += results.duration;\n\n        if (results.failed){\n            r.failedPages.push(page);\n        } else {\n            r.passedPages.push(page);\n        }\n\n        results.name = page;\n        results.type = \"page\";\n\n        r[page] = results;\n    },\n\n    /**\n     * Loads the next test page into the iframe.\n     * @return {Void}\n     * @method _run\n     * @static\n     * @private\n     */\n    _run : function () /*:Void*/ {\n\n        //set the current page\n        this._curPage = this._pages.shift();\n\n        this.fire(this.TEST_PAGE_BEGIN_EVENT, this._curPage);\n\n        //load the frame - destroy history in case there are other iframes that\n        //need testing\n        this._frame.location.replace(this._curPage);\n\n    },\n\n    //-------------------------------------------------------------------------\n    // Public Methods\n    //-------------------------------------------------------------------------\n\n    /**\n     * Signals that a test page has been loaded. This should be called from\n     * within the test page itself to notify the TestManager that it is ready.\n     * @return {Void}\n     * @method load\n     * @static\n     */\n    load : function () /*:Void*/ {\n        if (parent.YUITest.PageManager !== this){\n            parent.YUITest.PageManager.load();\n        } else {\n\n            if (this._frame) {\n                //assign event handling\n                var TestRunner = this._frame.YUITest.TestRunner;\n\n                TestRunner.subscribe(TestRunner.COMPLETE_EVENT, this._handleTestRunnerComplete, this, true);\n\n                //run it\n                TestRunner.run();\n            }\n        }\n    },\n\n    /**\n     * Sets the pages to be loaded.\n     * @param {String[]} pages An array of URLs to load.\n     * @return {Void}\n     * @method setPages\n     * @static\n     */\n    setPages : function (pages /*:String[]*/) /*:Void*/ {\n        this._pages = pages;\n    },\n\n    /**\n     * Begins the process of running the tests.\n     * @return {Void}\n     * @method start\n     * @static\n     */\n    start : function () /*:Void*/ {\n\n        if (!this._initialized) {\n\n            /**\n             * Fires when loading a test page\n             * @event testpagebegin\n             * @param curPage {string} the page being loaded\n             * @static\n             */\n\n            /**\n             * Fires when a test page is complete\n             * @event testpagecomplete\n             * @param obj {page: string, results: object} the name of the\n             * page that was loaded, and the test suite results\n             * @static\n             */\n\n            /**\n             * Fires when the test manager starts running all test pages\n             * @event testmanagerbegin\n             * @static\n             */\n\n            /**\n             * Fires when the test manager finishes running all test pages.  External\n             * test runners should subscribe to this event in order to get the\n             * aggregated test results.\n             * @event testmanagercomplete\n             * @param obj { pages_passed: int, pages_failed: int, tests_passed: int\n             *              tests_failed: int, passed: string[], failed: string[],\n             *              page_results: {} }\n             * @static\n             */\n\n            //create iframe if not already available\n            if (!this._frame){\n                var frame /*:HTMLElement*/ = document.createElement(\"iframe\");\n                frame.style.visibility = \"hidden\";\n                frame.style.position = \"absolute\";\n                document.body.appendChild(frame);\n                this._frame = frame.contentWindow || frame.contentDocument.parentWindow;\n            }\n\n            this._initialized = true;\n        }\n\n\n        // reset the results cache\n        this._results = {\n\n            passed: 0,\n            failed: 0,\n            ignored: 0,\n            total: 0,\n            type: \"report\",\n            name: \"YUI Test Results\",\n            duration: 0,\n            failedPages:[],\n            passedPages:[]\n            /*\n            // number of pages that pass\n            pages_passed: 0,\n            // number of pages that fail\n            pages_failed: 0,\n            // total number of tests passed\n            tests_passed: 0,\n            // total number of tests failed\n            tests_failed: 0,\n            // array of pages that passed\n            passed: [],\n            // array of pages that failed\n            failed: [],\n            // map of full results for each page\n            page_results: {}*/\n        };\n\n        this.fire(this.TEST_MANAGER_BEGIN_EVENT, null);\n        this._run();\n\n    },\n\n    /**\n     * Stops the execution of tests.\n     * @return {Void}\n     * @method stop\n     * @static\n     */\n    stop : function () /*:Void*/ {\n        clearTimeout(this._timeoutId);\n    }\n\n});\n\n\n    /**\n     * Runs test suites and test cases, providing events to allowing for the\n     * interpretation of test results.\n     * @namespace YUITest\n     * @class TestRunner\n     * @static\n     */\n    YUITest.TestRunner = function(){\n\n        /*(intentionally not documented)\n         * Determines if any of the array of test groups appears\n         * in the given TestRunner filter.\n         * @param {Array} testGroups The array of test groups to\n         *      search for.\n         * @param {String} filter The TestRunner groups filter.\n         */\n        function inGroups(testGroups, filter){\n            if (!filter.length){\n                return true;\n            } else {\n                if (testGroups){\n                    for (var i=0, len=testGroups.length; i < len; i++){\n                        if (filter.indexOf(\",\" + testGroups[i] + \",\") > -1){\n                            return true;\n                        }\n                    }\n                }\n                return false;\n            }\n        }\n\n        /**\n         * A node in the test tree structure. May represent a TestSuite, TestCase, or\n         * test function.\n         * @param {Variant} testObject A TestSuite, TestCase, or the name of a test function.\n         * @class TestNode\n         * @constructor\n         * @private\n         */\n        function TestNode(testObject){\n\n            /**\n             * The TestSuite, TestCase, or test function represented by this node.\n             * @type Variant\n             * @property testObject\n             */\n            this.testObject = testObject;\n\n            /**\n             * Pointer to this node's first child.\n             * @type TestNode\n             * @property firstChild\n             */\n            this.firstChild = null;\n\n            /**\n             * Pointer to this node's last child.\n             * @type TestNode\n             * @property lastChild\n             */\n            this.lastChild = null;\n\n            /**\n             * Pointer to this node's parent.\n             * @type TestNode\n             * @property parent\n             */\n            this.parent = null;\n\n            /**\n             * Pointer to this node's next sibling.\n             * @type TestNode\n             * @property next\n             */\n            this.next = null;\n\n            /**\n             * Test results for this test object.\n             * @type object\n             * @property results\n             */\n            this.results = new YUITest.Results();\n\n            //initialize results\n            if (testObject instanceof YUITest.TestSuite){\n                this.results.type = \"testsuite\";\n                this.results.name = testObject.name;\n            } else if (testObject instanceof YUITest.TestCase){\n                this.results.type = \"testcase\";\n                this.results.name = testObject.name;\n            }\n\n        }\n\n        TestNode.prototype = {\n\n            /**\n             * Appends a new test object (TestSuite, TestCase, or test function name) as a child\n             * of this node.\n             * @param {Variant} testObject A TestSuite, TestCase, or the name of a test function.\n             * @return {Void}\n             */\n            appendChild : function (testObject){\n                var node = new TestNode(testObject);\n                if (this.firstChild === null){\n                    this.firstChild = this.lastChild = node;\n                } else {\n                    this.lastChild.next = node;\n                    this.lastChild = node;\n                }\n                node.parent = this;\n                return node;\n            }\n        };\n\n        /**\n         * Runs test suites and test cases, providing events to allowing for the\n         * interpretation of test results.\n         * @namespace Test\n         * @class Runner\n         * @static\n         */\n        function TestRunner(){\n\n            //inherit from EventTarget\n            YUITest.EventTarget.call(this);\n\n            /**\n             * Suite on which to attach all TestSuites and TestCases to be run.\n             * @type YUITest.TestSuite\n             * @property masterSuite\n             * @static\n             * @private\n             */\n            this.masterSuite = new YUITest.TestSuite(\"yuitests\" + (new Date()).getTime());\n\n            /**\n             * Pointer to the current node in the test tree.\n             * @type TestNode\n             * @private\n             * @property _cur\n             * @static\n             */\n            this._cur = null;\n\n            /**\n             * Pointer to the root node in the test tree.\n             * @type TestNode\n             * @private\n             * @property _root\n             * @static\n             */\n            this._root = null;\n\n            /**\n             * Indicates if the TestRunner will log events or not.\n             * @type Boolean\n             * @property _log\n             * @private\n             * @static\n             */\n            this._log = true;\n\n            /**\n             * Indicates if the TestRunner is waiting as a result of\n             * wait() being called.\n             * @type Boolean\n             * @property _waiting\n             * @private\n             * @static\n             */\n            this._waiting = false;\n\n            /**\n             * Indicates if the TestRunner is currently running tests.\n             * @type Boolean\n             * @private\n             * @property _running\n             * @static\n             */\n            this._running = false;\n\n            /**\n             * Holds copy of the results object generated when all tests are\n             * complete.\n             * @type Object\n             * @private\n             * @property _lastResults\n             * @static\n             */\n            this._lastResults = null;\n\n            /**\n             * Data object that is passed around from method to method.\n             * @type Object\n             * @private\n             * @property _data\n             * @static\n             */\n            this._context = null;\n\n            /**\n             * The list of test groups to run. The list is represented\n             * by a comma delimited string with commas at the start and\n             * end.\n             * @type String\n             * @private\n             * @property _groups\n             * @static\n             */\n            this._groups = \"\";\n        }\n\n        TestRunner.prototype = YUITest.Util.mix(new YUITest.EventTarget(), {\n\n            //restore prototype\n            constructor: YUITest.TestRunner,\n\n            //-------------------------------------------------------------------------\n            // Constants\n            //-------------------------------------------------------------------------\n\n            /**\n             * Fires when a test case is opened but before the first\n             * test is executed.\n             * @event testcasebegin\n             * @static\n             */\n            TEST_CASE_BEGIN_EVENT : \"testcasebegin\",\n\n            /**\n             * Fires when all tests in a test case have been executed.\n             * @event testcasecomplete\n             * @static\n             */\n            TEST_CASE_COMPLETE_EVENT : \"testcasecomplete\",\n\n            /**\n             * Fires when a test suite is opened but before the first\n             * test is executed.\n             * @event testsuitebegin\n             * @static\n             */\n            TEST_SUITE_BEGIN_EVENT : \"testsuitebegin\",\n\n            /**\n             * Fires when all test cases in a test suite have been\n             * completed.\n             * @event testsuitecomplete\n             * @static\n             */\n            TEST_SUITE_COMPLETE_EVENT : \"testsuitecomplete\",\n\n            /**\n             * Fires when a test has passed.\n             * @event pass\n             * @static\n             */\n            TEST_PASS_EVENT : \"pass\",\n\n            /**\n             * Fires when a test has failed.\n             * @event fail\n             * @static\n             */\n            TEST_FAIL_EVENT : \"fail\",\n\n            /**\n             * Fires when a non-test method has an error.\n             * @event error\n             * @static\n             */\n            ERROR_EVENT : \"error\",\n\n            /**\n             * Fires when a test has been ignored.\n             * @event ignore\n             * @static\n             */\n            TEST_IGNORE_EVENT : \"ignore\",\n\n            /**\n             * Fires when all test suites and test cases have been completed.\n             * @event complete\n             * @static\n             */\n            COMPLETE_EVENT : \"complete\",\n\n            /**\n             * Fires when the run() method is called.\n             * @event begin\n             * @static\n             */\n            BEGIN_EVENT : \"begin\",\n\n            //-------------------------------------------------------------------------\n            // Test Tree-Related Methods\n            //-------------------------------------------------------------------------\n\n            /**\n             * Adds a test case to the test tree as a child of the specified node.\n             * @param {TestNode} parentNode The node to add the test case to as a child.\n             * @param {YUITest.TestCase} testCase The test case to add.\n             * @return {Void}\n             * @static\n             * @private\n             * @method _addTestCaseToTestTree\n             */\n           _addTestCaseToTestTree : function (parentNode, testCase){\n\n                //add the test suite\n                var node = parentNode.appendChild(testCase),\n                    prop,\n                    testName;\n\n                //iterate over the items in the test case\n                for (prop in testCase){\n                    if ((prop.indexOf(\"test\") === 0 || prop.indexOf(\" \") > -1) && typeof testCase[prop] == \"function\"){\n                        node.appendChild(prop);\n                    }\n                }\n\n            },\n\n            /**\n             * Adds a test suite to the test tree as a child of the specified node.\n             * @param {TestNode} parentNode The node to add the test suite to as a child.\n             * @param {YUITest.TestSuite} testSuite The test suite to add.\n             * @return {Void}\n             * @static\n             * @private\n             * @method _addTestSuiteToTestTree\n             */\n            _addTestSuiteToTestTree : function (parentNode, testSuite) {\n\n                //add the test suite\n                var node = parentNode.appendChild(testSuite);\n\n                //iterate over the items in the master suite\n                for (var i=0; i < testSuite.items.length; i++){\n                    if (testSuite.items[i] instanceof YUITest.TestSuite) {\n                        this._addTestSuiteToTestTree(node, testSuite.items[i]);\n                    } else if (testSuite.items[i] instanceof YUITest.TestCase) {\n                        this._addTestCaseToTestTree(node, testSuite.items[i]);\n                    }\n                }\n            },\n\n            /**\n             * Builds the test tree based on items in the master suite. The tree is a hierarchical\n             * representation of the test suites, test cases, and test functions. The resulting tree\n             * is stored in _root and the pointer _cur is set to the root initially.\n             * @return {Void}\n             * @static\n             * @private\n             * @method _buildTestTree\n             */\n            _buildTestTree : function () {\n\n                this._root = new TestNode(this.masterSuite);\n                //this._cur = this._root;\n\n                //iterate over the items in the master suite\n                for (var i=0; i < this.masterSuite.items.length; i++){\n                    if (this.masterSuite.items[i] instanceof YUITest.TestSuite) {\n                        this._addTestSuiteToTestTree(this._root, this.masterSuite.items[i]);\n                    } else if (this.masterSuite.items[i] instanceof YUITest.TestCase) {\n                        this._addTestCaseToTestTree(this._root, this.masterSuite.items[i]);\n                    }\n                }\n\n            },\n\n            //-------------------------------------------------------------------------\n            // Private Methods\n            //-------------------------------------------------------------------------\n\n            /**\n             * Handles the completion of a test object's tests. Tallies test results\n             * from one level up to the next.\n             * @param {TestNode} node The TestNode representing the test object.\n             * @return {Void}\n             * @method _handleTestObjectComplete\n             * @private\n             */\n            _handleTestObjectComplete : function (node) {\n                var parentNode;\n\n                if (typeof node.testObject == \"object\" && node !== null){\n                    parentNode = node.parent;\n\n                    if (parentNode){\n                        parentNode.results.include(node.results);\n                        parentNode.results[node.testObject.name] = node.results;\n                    }\n\n                    if (node.testObject instanceof YUITest.TestSuite){\n                        this._execNonTestMethod(node, \"tearDown\", false);\n                        node.results.duration = (new Date()) - node._start;\n                        this.fire({ type: this.TEST_SUITE_COMPLETE_EVENT, testSuite: node.testObject, results: node.results});\n                    } else if (node.testObject instanceof YUITest.TestCase){\n                        this._execNonTestMethod(node, \"destroy\", false);\n                        node.results.duration = (new Date()) - node._start;\n                        this.fire({ type: this.TEST_CASE_COMPLETE_EVENT, testCase: node.testObject, results: node.results});\n                    }\n                }\n            },\n\n            //-------------------------------------------------------------------------\n            // Navigation Methods\n            //-------------------------------------------------------------------------\n\n            /**\n             * Retrieves the next node in the test tree.\n             * @return {TestNode} The next node in the test tree or null if the end is reached.\n             * @private\n             * @static\n             * @method _next\n             */\n            _next : function () {\n\n                if (this._cur === null){\n                    this._cur = this._root;\n                } else if (this._cur.firstChild) {\n                    this._cur = this._cur.firstChild;\n                } else if (this._cur.next) {\n                    this._cur = this._cur.next;\n                } else {\n                    while (this._cur && !this._cur.next && this._cur !== this._root){\n                        this._handleTestObjectComplete(this._cur);\n                        this._cur = this._cur.parent;\n                    }\n\n                    this._handleTestObjectComplete(this._cur);\n\n                    if (this._cur == this._root){\n                        this._cur.results.type = \"report\";\n                        this._cur.results.timestamp = (new Date()).toLocaleString();\n                        this._cur.results.duration = (new Date()) - this._cur._start;\n                        this._lastResults = this._cur.results;\n                        this._running = false;\n                        this.fire({ type: this.COMPLETE_EVENT, results: this._lastResults});\n                        this._cur = null;\n                    } else {\n                        this._cur = this._cur.next;\n                    }\n                }\n\n                return this._cur;\n            },\n\n            /**\n             * Executes a non-test method (init, setUp, tearDown, destroy)\n             * and traps an errors. If an error occurs, an error event is\n             * fired.\n             * @param {Object} node The test node in the testing tree.\n             * @param {String} methodName The name of the method to execute.\n             * @param {Boolean} allowAsync Determines if the method can be called asynchronously.\n             * @return {Boolean} True if an async method was called, false if not.\n             * @method _execNonTestMethod\n             * @private\n             */\n            _execNonTestMethod: function(node, methodName, allowAsync){\n                var testObject = node.testObject,\n                    event = { type: this.ERROR_EVENT };\n                try {\n                    if (allowAsync && testObject[\"async:\" + methodName]){\n                        testObject[\"async:\" + methodName](this._context);\n                        return true;\n                    } else {\n                        testObject[methodName](this._context);\n                    }\n                } catch (ex){\n                    node.results.errors++;\n                    event.error = ex;\n                    event.methodName = methodName;\n                    if (testObject instanceof YUITest.TestCase){\n                        event.testCase = testObject;\n                    } else {\n                        event.testSuite = testSuite;\n                    }\n\n                    this.fire(event);\n                }\n\n                return false;\n            },\n\n            /**\n             * Runs a test case or test suite, returning the results.\n             * @param {YUITest.TestCase|YUITest.TestSuite} testObject The test case or test suite to run.\n             * @return {Object} Results of the execution with properties passed, failed, and total.\n             * @private\n             * @method _run\n             * @static\n             */\n            _run : function () {\n\n                //flag to indicate if the TestRunner should wait before continuing\n                var shouldWait = false;\n\n                //get the next test node\n                var node = this._next();\n\n                if (node !== null) {\n\n                    //set flag to say the testrunner is running\n                    this._running = true;\n\n                    //eliminate last results\n                    this._lastResult = null;\n\n                    var testObject = node.testObject;\n\n                    //figure out what to do\n                    if (typeof testObject == \"object\" && testObject !== null){\n                        if (testObject instanceof YUITest.TestSuite){\n                            this.fire({ type: this.TEST_SUITE_BEGIN_EVENT, testSuite: testObject });\n                            node._start = new Date();\n                            this._execNonTestMethod(node, \"setUp\" ,false);\n                        } else if (testObject instanceof YUITest.TestCase){\n                            this.fire({ type: this.TEST_CASE_BEGIN_EVENT, testCase: testObject });\n                            node._start = new Date();\n\n                            //regular or async init\n                            /*try {\n                                if (testObject[\"async:init\"]){\n                                    testObject[\"async:init\"](this._context);\n                                    return;\n                                } else {\n                                    testObject.init(this._context);\n                                }\n                            } catch (ex){\n                                node.results.errors++;\n                                this.fire({ type: this.ERROR_EVENT, error: ex, testCase: testObject, methodName: \"init\" });\n                            }*/\n                            if(this._execNonTestMethod(node, \"init\", true)){\n                                return;\n                            }\n                        }\n\n                        //some environments don't support setTimeout\n                        if (typeof setTimeout != \"undefined\"){\n                            setTimeout(function(){\n                                YUITest.TestRunner._run();\n                            }, 0);\n                        } else {\n                            this._run();\n                        }\n                    } else {\n                        this._runTest(node);\n                    }\n\n                }\n            },\n\n            _resumeTest : function (segment) {\n\n                //get relevant information\n                var node = this._cur;\n\n                //we know there's no more waiting now\n                this._waiting = false;\n\n                //if there's no node, it probably means a wait() was called after resume()\n                if (!node){\n                    //TODO: Handle in some way?\n                    //console.log(\"wait() called after resume()\");\n                    //this.fire(\"error\", { testCase: \"(unknown)\", test: \"(unknown)\", error: new Error(\"wait() called after resume()\")} );\n                    return;\n                }\n\n                var testName = node.testObject;\n                var testCase = node.parent.testObject;\n\n                //cancel other waits if available\n                if (testCase.__yui_wait){\n                    clearTimeout(testCase.__yui_wait);\n                    delete testCase.__yui_wait;\n                }\n\n                //get the \"should\" test cases\n                var shouldFail = testName.indexOf(\"fail:\") === 0 ||\n                                    (testCase._should.fail || {})[testName];\n                var shouldError = (testCase._should.error || {})[testName];\n\n                //variable to hold whether or not the test failed\n                var failed = false;\n                var error = null;\n\n                //try the test\n                try {\n\n                    //run the test\n                    segment.call(testCase, this._context);\n\n                    //if the test hasn't already failed and doesn't have any asserts...\n                    if(YUITest.Assert._getCount() == 0){\n                        throw new YUITest.AssertionError(\"Test has no asserts.\");\n                    }\n                    //if it should fail, and it got here, then it's a fail because it didn't\n                     else if (shouldFail){\n                        error = new YUITest.ShouldFail();\n                        failed = true;\n                    } else if (shouldError){\n                        error = new YUITest.ShouldError();\n                        failed = true;\n                    }\n\n                } catch (thrown){\n\n                    //cancel any pending waits, the test already failed\n                    if (testCase.__yui_wait){\n                        clearTimeout(testCase.__yui_wait);\n                        delete testCase.__yui_wait;\n                    }\n\n                    //figure out what type of error it was\n                    if (thrown instanceof YUITest.AssertionError) {\n                        if (!shouldFail){\n                            error = thrown;\n                            failed = true;\n                        }\n                    } else if (thrown instanceof YUITest.Wait){\n\n                        if (typeof thrown.segment == \"function\"){\n                            if (typeof thrown.delay == \"number\"){\n\n                                //some environments don't support setTimeout\n                                if (typeof setTimeout != \"undefined\"){\n                                    testCase.__yui_wait = setTimeout(function(){\n                                        YUITest.TestRunner._resumeTest(thrown.segment);\n                                    }, thrown.delay);\n                                    this._waiting = true;\n                                } else {\n                                    throw new Error(\"Asynchronous tests not supported in this environment.\");\n                                }\n                            }\n                        }\n\n                        return;\n\n                    } else {\n                        //first check to see if it should error\n                        if (!shouldError) {\n                            error = new YUITest.UnexpectedError(thrown);\n                            failed = true;\n                        } else {\n                            //check to see what type of data we have\n                            if (typeof shouldError == \"string\"){\n\n                                //if it's a string, check the error message\n                                if (thrown.message != shouldError){\n                                    error = new YUITest.UnexpectedError(thrown);\n                                    failed = true;\n                                }\n                            } else if (typeof shouldError == \"function\"){\n\n                                //if it's a function, see if the error is an instance of it\n                                if (!(thrown instanceof shouldError)){\n                                    error = new YUITest.UnexpectedError(thrown);\n                                    failed = true;\n                                }\n\n                            } else if (typeof shouldError == \"object\" && shouldError !== null){\n\n                                //if it's an object, check the instance and message\n                                if (!(thrown instanceof shouldError.constructor) ||\n                                        thrown.message != shouldError.message){\n                                    error = new YUITest.UnexpectedError(thrown);\n                                    failed = true;\n                                }\n\n                            }\n\n                        }\n                    }\n\n                }\n\n                //fire appropriate event\n                if (failed) {\n                    this.fire({ type: this.TEST_FAIL_EVENT, testCase: testCase, testName: testName, error: error });\n                } else {\n                    this.fire({ type: this.TEST_PASS_EVENT, testCase: testCase, testName: testName });\n                }\n\n                //run the tear down\n                this._execNonTestMethod(node.parent, \"tearDown\", false);\n\n                //reset the assert count\n                YUITest.Assert._reset();\n\n                //calculate duration\n                var duration = (new Date()) - node._start;\n\n                //update results\n                node.parent.results[testName] = {\n                    result: failed ? \"fail\" : \"pass\",\n                    message: error ? error.getMessage() : \"Test passed\",\n                    type: \"test\",\n                    name: testName,\n                    duration: duration\n                };\n\n                if (failed){\n                    node.parent.results.failed++;\n                } else {\n                    node.parent.results.passed++;\n                }\n                node.parent.results.total++;\n\n                //set timeout not supported in all environments\n                if (typeof setTimeout != \"undefined\"){\n                    setTimeout(function(){\n                        YUITest.TestRunner._run();\n                    }, 0);\n                } else {\n                    this._run();\n                }\n\n            },\n\n            /**\n             * Handles an error as if it occurred within the currently executing\n             * test. This is for mock methods that may be called asynchronously\n             * and therefore out of the scope of the TestRunner. Previously, this\n             * error would bubble up to the browser. Now, this method is used\n             * to tell TestRunner about the error. This should never be called\n             * by anyplace other than the Mock object.\n             * @param {Error} error The error object.\n             * @return {Void}\n             * @method _handleError\n             * @private\n             * @static\n             */\n            _handleError: function(error){\n\n                if (this._waiting){\n                    this._resumeTest(function(){\n                        throw error;\n                    });\n                } else {\n                    throw error;\n                }\n\n            },\n\n            /**\n             * Runs a single test based on the data provided in the node.\n             * @param {TestNode} node The TestNode representing the test to run.\n             * @return {Void}\n             * @static\n             * @private\n             * @name _runTest\n             */\n            _runTest : function (node) {\n\n                //get relevant information\n                var testName = node.testObject,\n                    testCase = node.parent.testObject,\n                    test = testCase[testName],\n\n                    //get the \"should\" test cases\n                    shouldIgnore = testName.indexOf(\"ignore:\") === 0 ||\n                                    !inGroups(testCase.groups, this._groups) ||\n                                    (testCase._should.ignore || {})[testName];   //deprecated\n\n                //figure out if the test should be ignored or not\n                if (shouldIgnore){\n\n                    //update results\n                    node.parent.results[testName] = {\n                        result: \"ignore\",\n                        message: \"Test ignored\",\n                        type: \"test\",\n                        name: testName.indexOf(\"ignore:\") === 0 ? testName.substring(7) : testName\n                    };\n\n                    node.parent.results.ignored++;\n                    node.parent.results.total++;\n\n                    this.fire({ type: this.TEST_IGNORE_EVENT,  testCase: testCase, testName: testName });\n\n                    //some environments don't support setTimeout\n                    if (typeof setTimeout != \"undefined\"){\n                        setTimeout(function(){\n                            YUITest.TestRunner._run();\n                        }, 0);\n                    } else {\n                        this._run();\n                    }\n\n                } else {\n\n                    //mark the start time\n                    node._start = new Date();\n\n                    //run the setup\n                    this._execNonTestMethod(node.parent, \"setUp\", false);\n\n                    //now call the body of the test\n                    this._resumeTest(test);\n                }\n\n            },\n\n            //-------------------------------------------------------------------------\n            // Misc Methods\n            //-------------------------------------------------------------------------\n\n            /**\n             * Retrieves the name of the current result set.\n             * @return {String} The name of the result set.\n             * @method getName\n             */\n            getName: function(){\n                return this.masterSuite.name;\n            },\n\n            /**\n             * The name assigned to the master suite of the TestRunner. This is the name\n             * that is output as the root's name when results are retrieved.\n             * @param {String} name The name of the result set.\n             * @return {Void}\n             * @method setName\n             */\n            setName: function(name){\n                this.masterSuite.name = name;\n            },\n\n            //-------------------------------------------------------------------------\n            // Public Methods\n            //-------------------------------------------------------------------------\n\n            /**\n             * Adds a test suite or test case to the list of test objects to run.\n             * @param testObject Either a TestCase or a TestSuite that should be run.\n             * @return {Void}\n             * @method add\n             * @static\n             */\n            add : function (testObject) {\n                this.masterSuite.add(testObject);\n                return this;\n            },\n\n            /**\n             * Removes all test objects from the runner.\n             * @return {Void}\n             * @method clear\n             * @static\n             */\n            clear : function () {\n                this.masterSuite = new YUITest.TestSuite(\"yuitests\" + (new Date()).getTime());\n            },\n\n            /**\n             * Indicates if the TestRunner is waiting for a test to resume\n             * @return {Boolean} True if the TestRunner is waiting, false if not.\n             * @method isWaiting\n             * @static\n             */\n            isWaiting: function() {\n                return this._waiting;\n            },\n\n            /**\n             * Indicates that the TestRunner is busy running tests and therefore can't\n             * be stopped and results cannot be gathered.\n             * @return {Boolean} True if the TestRunner is running, false if not.\n             * @method isRunning\n             */\n            isRunning: function(){\n                return this._running;\n            },\n\n            /**\n             * Returns the last complete results set from the TestRunner. Null is returned\n             * if the TestRunner is running or no tests have been run.\n             * @param {Function} format (Optional) A test format to return the results in.\n             * @return {Object|String} Either the results object or, if a test format is\n             *      passed as the argument, a string representing the results in a specific\n             *      format.\n             * @method getResults\n             */\n            getResults: function(format){\n                if (!this._running && this._lastResults){\n                    if (typeof format == \"function\"){\n                        return format(this._lastResults);\n                    } else {\n                        return this._lastResults;\n                    }\n                } else {\n                    return null;\n                }\n            },\n\n            /**\n             * Returns the coverage report for the files that have been executed.\n             * This returns only coverage information for files that have been\n             * instrumented using YUI Test Coverage and only those that were run\n             * in the same pass.\n             * @param {Function} format (Optional) A coverage format to return results in.\n             * @return {Object|String} Either the coverage object or, if a coverage\n             *      format is specified, a string representing the results in that format.\n             * @method getCoverage\n             */\n            getCoverage: function(format){\n                if (!this._running && typeof _yuitest_coverage == \"object\"){\n                    if (typeof format == \"function\"){\n                        return format(_yuitest_coverage);\n                    } else {\n                        return _yuitest_coverage;\n                    }\n                } else {\n                    return null;\n                }\n            },\n\n            /**\n             * Used to continue processing when a method marked with\n             * \"async:\" is executed. This should not be used in test\n             * methods, only in init(). Each argument is a string, and\n             * when the returned function is executed, the arguments\n             * are assigned to the context data object using the string\n             * as the key name (value is the argument itself).\n             * @private\n             * @return {Function} A callback function.\n             */\n            callback: function(){\n                var names   = arguments,\n                    data    = this._context,\n                    that    = this;\n\n                return function(){\n                    for (var i=0; i < arguments.length; i++){\n                        data[names[i]] = arguments[i];\n                    }\n                    that._run();\n                };\n            },\n\n            /**\n             * Resumes the TestRunner after wait() was called.\n             * @param {Function} segment The function to run as the rest\n             *      of the haulted test.\n             * @return {Void}\n             * @method resume\n             * @static\n             */\n            resume : function (segment) {\n                if (this._waiting){\n                    this._resumeTest(segment || function(){});\n                } else {\n                    throw new Error(\"resume() called without wait().\");\n                }\n            },\n\n            /**\n             * Runs the test suite.\n             * @param {Object|Boolean} options (Optional) Options for the runner:\n             *      <code>oldMode</code> indicates the TestRunner should work in the YUI <= 2.8 way\n             *      of internally managing test suites. <code>groups</code> is an array\n             *      of test groups indicating which tests to run.\n             * @return {Void}\n             * @method run\n             * @static\n             */\n            run : function (options) {\n\n                options = options || {};\n\n                //pointer to runner to avoid scope issues\n                var runner  = YUITest.TestRunner,\n                    oldMode = options.oldMode;\n\n\n                //if there's only one suite on the masterSuite, move it up\n                if (!oldMode && this.masterSuite.items.length == 1 && this.masterSuite.items[0] instanceof YUITest.TestSuite){\n                    this.masterSuite = this.masterSuite.items[0];\n                }\n\n                //determine if there are any groups to filter on\n                runner._groups = (options.groups instanceof Array) ? \",\" + options.groups.join(\",\") + \",\" : \"\";\n\n                //initialize the runner\n                runner._buildTestTree();\n                runner._context = {};\n                runner._root._start = new Date();\n\n                //fire the begin event\n                runner.fire(runner.BEGIN_EVENT);\n\n                //begin the testing\n                runner._run();\n            }\n        });\n\n        return new TestRunner();\n\n    }();\n/**\n * Main CSSLint object.\n * @class CSSLint\n * @static\n * @extends parserlib.util.EventTarget\n */\nvar CSSLint = (function(){\n\n    var rules      = [],\n        formatters = [],\n        api        = new parserlib.util.EventTarget();\n        \n    api.version = \"@VERSION@\";\n\n    //-------------------------------------------------------------------------\n    // Rule Management\n    //-------------------------------------------------------------------------\n\n    /**\n     * Adds a new rule to the engine.\n     * @param {Object} rule The rule to add.\n     * @method addRule\n     */\n    api.addRule = function(rule){\n        rules.push(rule);\n        rules[rule.id] = rule;\n    };\n\n    /**\n     * Clears all rule from the engine.\n     * @method clearRules\n     */\n    api.clearRules = function(){\n        rules = [];\n    };\n\n    //-------------------------------------------------------------------------\n    // Formatters\n    //-------------------------------------------------------------------------\n\n    /**\n     * Adds a new formatter to the engine.\n     * @param {Object} formatter The formatter to add.\n     * @method addFormatter\n     */\n    api.addFormatter = function(formatter) {\n        // formatters.push(formatter);\n        formatters[formatter.id] = formatter;\n    };\n    \n    /**\n     * Retrieves a formatter for use.\n     * @param {String} formatId The name of the format to retrieve.\n     * @return {Object} The formatter or undefined.\n     * @method getFormatter\n     */\n    api.getFormatter = function(formatId){\n        return formatters[formatId];\n    };\n    \n    /**\n     * Formats the results in a particular format for a single file.\n     * @param {Object} result The results returned from CSSLint.verify().\n     * @param {String} filename The filename for which the results apply.\n     * @param {String} formatId The name of the formatter to use.\n     * @return {String} A formatted string for the results.\n     * @method format\n     */\n    api.format = function(results, filename, formatId) {\n        var formatter = this.getFormatter(formatId),\n            result = null;\n            \n        if (formatter){\n            result = formatter.startFormat();\n            result += formatter.formatResults(results, filename);\n            result += formatter.endFormat();\n        }\n        \n        return result;\n    }    \n    \n    /**\n     * Indicates if the given format is supported.\n     * @param {String} formatId The ID of the format to check.\n     * @return {Boolean} True if the format exists, false if not.\n     * @method hasFormat\n     */\n    api.hasFormat = function(formatId){\n        return formatters.hasOwnProperty(formatId);\n    };\n\n    //-------------------------------------------------------------------------\n    // Verification\n    //-------------------------------------------------------------------------\n\n    /**\n     * Starts the verification process for the given CSS text.\n     * @param {String} text The CSS text to verify.\n     * @param {Object} ruleset (Optional) List of rules to apply. If null, then\n     *      all rules are used.\n     * @return {Object} Results of the verification.\n     * @method verify\n     */\n    api.verify = function(text, ruleset){\n\n        var i       = 0,\n            len     = rules.length,\n            reporter,\n            lines,\n            parser = new parserlib.css.Parser({ starHack: true, ieFilters: true,\n                                                underscoreHack: true, strict: false });\n\n        lines = text.split(/\\n\\r?/g);\n        reporter = new Reporter(lines);\n\n        if (!ruleset){\n            while (i < len){\n                rules[i++].init(parser, reporter);\n            }\n        } else {\n            ruleset.errors = 1;       //always report parsing errors\n            for (i in ruleset){\n                if(ruleset.hasOwnProperty(i)){\n                    if (rules[i]){\n                        rules[i].init(parser, reporter);\n                    }\n                }\n            }\n        }\n\n        //capture most horrible error type\n        try {\n            parser.parse(text);\n        } catch (ex) {\n            reporter.error(\"Fatal error, cannot continue: \" + ex.message, ex.line, ex.col);\n        }\n\n        return {\n            messages    : reporter.messages,\n            stats       : reporter.stats\n        };\n    };\n\n    //-------------------------------------------------------------------------\n    // Publish the API\n    //-------------------------------------------------------------------------\n\n    return api;\n\n})();\n/**\n * An instance of Report is used to report results of the\n * verification back to the main API.\n * @class Reporter\n * @constructor\n * @param {String[]} lines The text lines of the source.\n */\nfunction Reporter(lines){\n\n    /**\n     * List of messages being reported.\n     * @property messages\n     * @type String[]\n     */\n    this.messages = [];\n\n    /**\n     * List of statistics being reported.\n     * @property stats\n     * @type String[]\n     */\n    this.stats = [];\n\n    /**\n     * Lines of code being reported on. Used to provide contextual information\n     * for messages.\n     * @property lines\n     * @type String[]\n     */\n    this.lines = lines;\n}\n\nReporter.prototype = {\n\n    //restore constructor\n    constructor: Reporter,\n\n    /**\n     * Report an error.\n     * @param {String} message The message to store.\n     * @param {int} line The line number.\n     * @param {int} col The column number.\n     * @param {Object} rule The rule this message relates to.\n     * @method error\n     */\n    error: function(message, line, col, rule){\n        this.messages.push({\n            type    : \"error\",\n            line    : line,\n            col     : col,\n            message : message,\n            evidence: this.lines[line-1],\n            rule    : rule\n        });\n    },\n\n    /**\n     * Report an warning.\n     * @param {String} message The message to store.\n     * @param {int} line The line number.\n     * @param {int} col The column number.\n     * @param {Object} rule The rule this message relates to.\n     * @method warn\n     */\n    warn: function(message, line, col, rule){\n        this.messages.push({\n            type    : \"warning\",\n            line    : line,\n            col     : col,\n            message : message,\n            evidence: this.lines[line-1],\n            rule    : rule\n        });\n    },\n\n    /**\n     * Report some informational text.\n     * @param {String} message The message to store.\n     * @param {int} line The line number.\n     * @param {int} col The column number.\n     * @param {Object} rule The rule this message relates to.\n     * @method info\n     */\n    info: function(message, line, col, rule){\n        this.messages.push({\n            type    : \"info\",\n            line    : line,\n            col     : col,\n            message : message,\n            evidence: this.lines[line-1],\n            rule    : rule\n        });\n    },\n\n    /**\n     * Report some rollup error information.\n     * @param {String} message The message to store.\n     * @param {Object} rule The rule this message relates to.\n     * @method rollupError\n     */\n    rollupError: function(message, rule){\n        this.messages.push({\n            type    : \"error\",\n            rollup  : true,\n            message : message,\n            rule    : rule\n        });\n    },\n\n    /**\n     * Report some rollup warning information.\n     * @param {String} message The message to store.\n     * @param {Object} rule The rule this message relates to.\n     * @method rollupWarn\n     */\n    rollupWarn: function(message, rule){\n        this.messages.push({\n            type    : \"warning\",\n            rollup  : true,\n            message : message,\n            rule    : rule\n        });\n    },\n\n    /**\n     * Report a statistic.\n     * @param {String} name The name of the stat to store.\n     * @param {Variant} value The value of the stat.\n     * @method stat\n     */\n    stat: function(name, value){\n        this.stats[name] = value;\n    }\n};\n/*\n * Utility functions that make life easier.\n */\n\n/*\n * Adds all properties from supplier onto receiver,\n * overwriting if the same name already exists on\n * reciever.\n * @param {Object} The object to receive the properties.\n * @param {Object} The object to provide the properties.\n * @return {Object} The receiver\n */\nfunction mix(reciever, supplier){\n    var prop;\n\n    for (prop in supplier){\n        if (supplier.hasOwnProperty(prop)){\n            receiver[prop] = supplier[prop];\n        }\n    }\n\n    return prop;\n}\n\n/*\n * Polyfill for array indexOf() method.\n * @param {Array} values The array to search.\n * @param {Variant} value The value to search for.\n * @return {int} The index of the value if found, -1 if not.\n */\nfunction indexOf(values, value){\n    if (values.indexOf){\n        return values.indexOf(value);\n    } else {\n        for (var i=0, len=values.length; i < len; i++){\n            if (values[i] === value){\n                return i;\n            }\n        }\n        return -1;\n    }\n}\n/*\n * Rule: Don't use adjoining classes (.foo.bar).\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"adjoining-classes\",\n    name: \"Adjoining Classes\",\n    desc: \"Don't use adjoining classes.\",\n    browsers: \"IE6\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                modifier,\n                classCount,\n                i, j, k;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n                for (j=0; j < selector.parts.length; j++){\n                    part = selector.parts[j];\n                    if (part instanceof parserlib.css.SelectorPart){\n                        classCount = 0;\n                        for (k=0; k < part.modifiers.length; k++){\n                            modifier = part.modifiers[k];\n                            if (modifier.type == \"class\"){\n                                classCount++;\n                            }\n                            if (classCount > 1){\n                                reporter.warn(\"Don't use adjoining classes.\", part.line, part.col, rule);\n                            }\n                        }\n                    }\n                }\n            }\n        });\n    }\n\n});\n/*\n * Rule: Don't use width or height when using padding or border. \n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"box-model\",\n    name: \"Box Model\",\n    desc: \"Don't use width or height when using padding or border.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            widthProperties = {\n                border: 1,\n                \"border-left\": 1,\n                \"border-right\": 1,\n                padding: 1,\n                \"padding-left\": 1,\n                \"padding-right\": 1\n            },\n            heightProperties = {\n                border: 1,\n                \"border-bottom\": 1,\n                \"border-top\": 1,\n                padding: 1,\n                \"padding-bottom\": 1,\n                \"padding-top\": 1\n            },\n            properties;\n\n        parser.addListener(\"startrule\", function(){\n            properties = {\n            };\n        });\n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text.toLowerCase();\n            \n            if (heightProperties[name] || widthProperties[name]){\n                if (!/^0\\S*$/.test(event.value) && !(name == \"border\" && event.value == \"none\")){\n                    properties[name] = { line: event.property.line, col: event.property.col };\n                }\n            } else {\n                if (name == \"width\" || name == \"height\"){\n                    properties[name] = 1;\n                }\n            }\n            \n        });\n\n        parser.addListener(\"endrule\", function(){\n            var prop;\n            if (properties[\"height\"]){\n                for (prop in heightProperties){\n                    if (heightProperties.hasOwnProperty(prop) && properties[prop]){\n                        reporter.warn(\"Broken box model: using height with \" + prop + \".\", properties[prop].line, properties[prop].col, rule);\n                    }\n                }\n            }\n\n            if (properties[\"width\"]){\n                for (prop in widthProperties){\n                    if (widthProperties.hasOwnProperty(prop) && properties[prop]){\n                        reporter.warn(\"Broken box model: using width with \" + prop + \".\", properties[prop].line, properties[prop].col, rule);\n                    }\n                }\n            }\n\n        });\n    }\n\n});\n/*\n * Rule: Include all compatible vendor prefixes to reach a wider\n * range of users.\n */\n/*global CSSLint*/ \nCSSLint.addRule({\n\n    //rule information\n    id: \"compatible-vendor-prefixes\",\n    name: \"Compatible Vendor Prefixes\",\n    desc: \"Include all compatible vendor prefixes to reach a wider range of users.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function (parser, reporter) {\n        var rule = this,\n            compatiblePrefixes,\n            properties,\n            prop,\n            variations,\n            prefixed,\n            i,\n            len,\n            arrayPush = Array.prototype.push,\n            applyTo = [];\n\n        // See http://peter.sh/experiments/vendor-prefixed-css-property-overview/ for details\n        compatiblePrefixes = {\n            \"animation\"                  : \"webkit moz\",\n            \"animation-delay\"            : \"webkit moz\",\n            \"animation-direction\"        : \"webkit moz\",\n            \"animation-duration\"         : \"webkit moz\",\n            \"animation-fill-mode\"        : \"webkit moz\",\n            \"animation-iteration-count\"  : \"webkit moz\",\n            \"animation-name\"             : \"webkit moz\",\n            \"animation-play-state\"       : \"webkit moz\",\n            \"animation-timing-function\"  : \"webkit moz\",\n            \"appearance\"                 : \"webkit moz\",\n            \"border-end\"                 : \"webkit moz\",\n            \"border-end-color\"           : \"webkit moz\",\n            \"border-end-style\"           : \"webkit moz\",\n            \"border-end-width\"           : \"webkit moz\",\n            \"border-image\"               : \"webkit moz o\",\n            \"border-radius\"              : \"webkit moz\",\n            \"border-start\"               : \"webkit moz\",\n            \"border-start-color\"         : \"webkit moz\",\n            \"border-start-style\"         : \"webkit moz\",\n            \"border-start-width\"         : \"webkit moz\",\n            \"box-align\"                  : \"webkit moz ms\",\n            \"box-direction\"              : \"webkit moz ms\",\n            \"box-flex\"                   : \"webkit moz ms\",\n            \"box-lines\"                  : \"webkit ms\",\n            \"box-ordinal-group\"          : \"webkit moz ms\",\n            \"box-orient\"                 : \"webkit moz ms\",\n            \"box-pack\"                   : \"webkit moz ms\",\n            \"box-sizing\"                 : \"webkit moz\",\n            \"box-shadow\"                 : \"webkit moz\",\n            \"column-count\"               : \"webkit moz\",\n            \"column-gap\"                 : \"webkit moz\",\n            \"column-rule\"                : \"webkit moz\",\n            \"column-rule-color\"          : \"webkit moz\",\n            \"column-rule-style\"          : \"webkit moz\",\n            \"column-rule-width\"          : \"webkit moz\",\n            \"column-width\"               : \"webkit moz\",\n            \"hyphens\"                    : \"epub moz\",\n            \"line-break\"                 : \"webkit ms\",\n            \"margin-end\"                 : \"webkit moz\",\n            \"margin-start\"               : \"webkit moz\",\n            \"marquee-speed\"              : \"webkit wap\",\n            \"marquee-style\"              : \"webkit wap\",\n            \"padding-end\"                : \"webkit moz\",\n            \"padding-start\"              : \"webkit moz\",\n            \"tab-size\"                   : \"moz o\",\n            \"text-size-adjust\"           : \"webkit ms\",\n            \"transform\"                  : \"webkit moz ms o\",\n            \"transform-origin\"           : \"webkit moz ms o\",\n            \"transition\"                 : \"webkit moz o\",\n            \"transition-delay\"           : \"webkit moz o\",\n            \"transition-duration\"        : \"webkit moz o\",\n            \"transition-property\"        : \"webkit moz o\",\n            \"transition-timing-function\" : \"webkit moz o\",\n            \"user-modify\"                : \"webkit moz\",\n            \"user-select\"                : \"webkit moz\",\n            \"word-break\"                 : \"epub ms\",\n            \"writing-mode\"               : \"epub ms\"\n        };\n\n        for (prop in compatiblePrefixes) {\n            if (compatiblePrefixes.hasOwnProperty(prop)) {\n                variations = [];\n                prefixed = compatiblePrefixes[prop].split(' ');\n                for (i = 0, len = prefixed.length; i < len; i++) {\n                    variations.push('-' + prefixed[i] + '-' + prop);\n                }\n                compatiblePrefixes[prop] = variations;\n                arrayPush.apply(applyTo, variations);\n            }\n        }\n        parser.addListener(\"startrule\", function () {\n            properties = [];\n        });\n\n        parser.addListener(\"property\", function (event) {\n            var name = event.property.text;\n            if (applyTo.indexOf(name) > -1) {\n                properties.push(name);\n            }\n        });\n\n        parser.addListener(\"endrule\", function (event) {\n            if (!properties.length) {\n                return;\n            }\n\n            var propertyGroups = {},\n                i,\n                len,\n                name,\n                prop,\n                variations,\n                value,\n                full,\n                actual,\n                item,\n                propertiesSpecified;\n\n            for (i = 0, len = properties.length; i < len; i++) {\n                name = properties[i];\n\n                for (prop in compatiblePrefixes) {\n                    if (compatiblePrefixes.hasOwnProperty(prop)) {\n                        variations = compatiblePrefixes[prop];\n                        if (variations.indexOf(name) > -1) {\n                            if (propertyGroups[prop] === undefined) {\n                                propertyGroups[prop] = {\n                                    full : variations.slice(0),\n                                    actual : []\n                                };\n                            }\n                            if (propertyGroups[prop].actual.indexOf(name) === -1) {\n                                propertyGroups[prop].actual.push(name);\n                            }\n                        }\n                    }\n                }\n            }\n\n            for (prop in propertyGroups) {\n                if (propertyGroups.hasOwnProperty(prop)) {\n                    value = propertyGroups[prop];\n                    full = value.full;\n                    actual = value.actual;\n\n                    if (full.length > actual.length) {\n                        for (i = 0, len = full.length; i < len; i++) {\n                            item = full[i];\n                            if (actual.indexOf(item) === -1) {\n                                propertiesSpecified = (actual.length === 1) ? actual[0] : (actual.length == 2) ? actual.join(\" and \") : actual.join(\", \");\n                                reporter.warn(\"The property \" + item + \" is compatible with \" + propertiesSpecified + \" and should be included as well.\", event.selectors[0].line, event.selectors[0].col, rule); \n                            }\n                        }\n\n                    }\n                }\n            }\n        });\n    }\n});\n/*\n * Rule: Certain properties don't play well with certain display values. \n * - float should not be used with inline-block\n * - height, width, margin-top, margin-bottom, float should not be used with inline\n * - vertical-align should not be used with block\n * - margin, float should not be used with table-*\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"display-property-grouping\",\n    name: \"Display Property Grouping\",\n    desc: \"Certain properties shouldn't be used with certain display property values.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        var propertiesToCheck = {\n                display: 1,\n                \"float\": \"none\",\n                height: 1,\n                width: 1,\n                margin: 1,\n                \"margin-left\": 1,\n                \"margin-right\": 1,\n                \"margin-bottom\": 1,\n                \"margin-top\": 1,\n                padding: 1,\n                \"padding-left\": 1,\n                \"padding-right\": 1,\n                \"padding-bottom\": 1,\n                \"padding-top\": 1,\n                \"vertical-align\": 1\n            },\n            properties;\n\n        parser.addListener(\"startrule\", function(){\n            properties = {};\n        });\n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text.toLowerCase();\n\n            if (propertiesToCheck[name]){\n                properties[name] = { value: event.value.text, line: event.property.line, col: event.property.col };                    \n            }\n        });\n\n        parser.addListener(\"endrule\", function(){\n\n            var display = properties.display ? properties.display.value : null;\n            if (display){\n                switch(display){\n\n                    case \"inline\":\n                        //height, width, margin-top, margin-bottom, float should not be used with inline\n                        reportProperty(\"height\", display);\n                        reportProperty(\"width\", display);\n                        reportProperty(\"margin\", display);\n                        reportProperty(\"margin-top\", display);\n                        reportProperty(\"margin-bottom\", display);              \n                        reportProperty(\"float\", display, \"display:inline has no effect on floated elements (but may be used to fix the IE6 double-margin bug).\");\n                        break;\n\n                    case \"block\":\n                        //vertical-align should not be used with block\n                        reportProperty(\"vertical-align\", display);\n                        break;\n\n                    case \"inline-block\":\n                        //float should not be used with inline-block\n                        reportProperty(\"float\", display);\n                        break;\n\n                    default:\n                        //margin, float should not be used with table\n                        if (display.indexOf(\"table-\") == 0){\n                            reportProperty(\"margin\", display);\n                            reportProperty(\"margin-left\", display);\n                            reportProperty(\"margin-right\", display);\n                            reportProperty(\"margin-top\", display);\n                            reportProperty(\"margin-bottom\", display);\n                            reportProperty(\"float\", display);\n                        }\n\n                        //otherwise do nothing\n                }\n            }\n          \n        });\n\n\n        function reportProperty(name, display, msg){\n            if (properties[name]){\n                if (!(typeof propertiesToCheck[name] == \"string\") || properties[name].value.toLowerCase() != propertiesToCheck[name]){\n                    reporter.warn(msg || name + \" can't be used with display: \" + display + \".\", properties[name].line, properties[name].col, rule);\n                }\n            }\n        }\n    }\n\n});\n/*\n * Rule: Duplicate properties must appear one after the other. If an already-defined\n * property appears somewhere else in the rule, then it's likely an error.\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"duplicate-properties\",\n    name: \"Duplicate Properties\",\n    desc: \"Duplicate properties must appear one after the other.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            properties,\n            lastProperty;            \n            \n        function startRule(event){\n            properties = {};        \n        }\n        \n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n        parser.addListener(\"startpage\", startRule);\n        \n        parser.addListener(\"property\", function(event){\n            var property = event.property,\n                name = property.text.toLowerCase();\n            \n            if (properties[name] && (lastProperty != name || properties[name] == event.value.text)){\n                reporter.warn(\"Duplicate property '\" + event.property + \"' found.\", event.line, event.col, rule);\n            }\n            \n            properties[name] = event.value.text;\n            lastProperty = name;\n                        \n        });\n            \n        \n    }\n\n});\n/*\n * Rule: Style rules without any properties defined should be removed.\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"empty-rules\",\n    name: \"Empty Rules\",\n    desc: \"Rules without any properties specified should be removed.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            count = 0;\n\n        parser.addListener(\"startrule\", function(){\n            count=0;\n        });\n\n        parser.addListener(\"property\", function(){\n            count++;\n        });\n\n        parser.addListener(\"endrule\", function(event){\n            var selectors = event.selectors;\n            if (count == 0){\n                reporter.warn(\"Rule is empty.\", selectors[0].line, selectors[0].col, rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: There should be no syntax errors. (Duh.)\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"errors\",\n    name: \"Parsing Errors\",\n    desc: \"This rule looks for recoverable syntax errors.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        parser.addListener(\"error\", function(event){\n            reporter.error(event.message, event.line, event.col, rule);\n        });\n\n    }\n\n});\n/*\n * Rule: You shouldn't use more than 10 floats. If you do, there's probably\n * room for some abstraction.\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"floats\",\n    name: \"Floats\",\n    desc: \"This rule tests if the float property is used too many times\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n        var count = 0;\n\n        //count how many times \"float\" is used\n        parser.addListener(\"property\", function(event){\n            if (event.property.text.toLowerCase() == \"float\" &&\n                    event.value.text.toLowerCase() != \"none\"){\n                count++;\n            }\n        });\n\n        //report the results\n        parser.addListener(\"endstylesheet\", function(){\n            reporter.stat(\"floats\", count);\n            if (count >= 10){\n                reporter.rollupWarn(\"Too many floats (\" + count + \"), you're probably using them for layout. Consider using a grid system instead.\", rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: Avoid too many @font-face declarations in the same stylesheet.\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"font-faces\",\n    name: \"Font Faces\",\n    desc: \"Too many different web fonts in the same stylesheet.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            count = 0;\n\n\n        parser.addListener(\"startfontface\", function(){\n            count++;\n        });\n\n        parser.addListener(\"endstylesheet\", function(){\n            if (count > 5){\n                reporter.rollupWarn(\"Too many @font-face declarations (\" + count + \").\", rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: You shouldn't need more than 9 font-size declarations.\n */\n\nCSSLint.addRule({\n\n    //rule information\n    id: \"font-sizes\",\n    name: \"Font Sizes\",\n    desc: \"Checks the number of font-size declarations.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            count = 0;\n\n        //check for use of \"font-size\"\n        parser.addListener(\"property\", function(event){\n            if (event.property == \"font-size\"){\n                count++;\n            }\n        });\n\n        //report the results\n        parser.addListener(\"endstylesheet\", function(){\n            reporter.stat(\"font-sizes\", count);\n            if (count >= 10){\n                reporter.rollupWarn(\"Too many font-size declarations (\" + count + \"), abstraction needed.\", rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: When using a vendor-prefixed gradient, make sure to use them all.\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"gradients\",\n    name: \"Gradients\",\n    desc: \"When using a vendor-prefixed gradient, make sure to use them all.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            gradients;\n\n        parser.addListener(\"startrule\", function(){\n            gradients = {\n                moz: 0,\n                webkit: 0,\n                ms: 0,\n                o: 0\n            };\n        });\n\n        parser.addListener(\"property\", function(event){\n\n            if (/\\-(moz|ms|o|webkit)(?:\\-(?:linear|radial))\\-gradient/.test(event.value)){\n                gradients[RegExp.$1] = 1;\n            }\n\n        });\n\n        parser.addListener(\"endrule\", function(event){\n            var missing = [];\n\n            if (!gradients.moz){\n                missing.push(\"Firefox 3.6+\");\n            }\n\n            if (!gradients.webkit){\n                missing.push(\"Webkit (Safari, Chrome)\");\n            }\n\n            if (!gradients.ms){\n                missing.push(\"Internet Explorer 10+\");\n            }\n\n            if (!gradients.o){\n                missing.push(\"Opera 11.1+\");\n            }\n\n            if (missing.length && missing.length < 4){            \n                reporter.warn(\"Missing vendor-prefixed CSS gradients for \" + missing.join(\", \") + \".\", event.selectors[0].line, event.selectors[0].col, rule); \n            }\n\n        });\n\n    }\n\n});\n/*\n * Rule: Don't use IDs for selectors.\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"ids\",\n    name: \"IDs\",\n    desc: \"Selectors should not contain IDs.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                modifier,\n                idCount,\n                i, j, k;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n                idCount = 0;\n\n                for (j=0; j < selector.parts.length; j++){\n                    part = selector.parts[j];\n                    if (part instanceof parserlib.css.SelectorPart){\n                        for (k=0; k < part.modifiers.length; k++){\n                            modifier = part.modifiers[k];\n                            if (modifier.type == \"id\"){\n                                idCount++;\n                            }\n                        }\n                    }\n                }\n\n                if (idCount == 1){\n                    reporter.warn(\"Don't use IDs in selectors.\", selector.line, selector.col, rule);\n                } else if (idCount > 1){\n                    reporter.warn(idCount + \" IDs in the selector, really?\", selector.line, selector.col, rule);\n                }\n            }\n\n        });\n    }\n\n});\n/*\n * Rule: Don't use @import, use <link> instead.\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"import\",\n    name: \"@import\",\n    desc: \"Don't use @import, use <link> instead.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n        \n        parser.addListener(\"import\", function(event){        \n            reporter.warn(\"@import prevents parallel downloads, use <link> instead.\", event.line, event.col, rule);\n        });\n\n    }\n\n});\n/*\n * Rule: Make sure !important is not overused, this could lead to specificity\n * war. Display a warning on !important declarations, an error if it's\n * used more at least 10 times.\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"important\",\n    name: \"Important\",\n    desc: \"Be careful when using !important declaration\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n        var count = 0;\n\n        //warn that important is used and increment the declaration counter\n        parser.addListener(\"property\", function(event){\n            var name = event.property;\n            if (event.important === true){\n                count++;\n                reporter.warn(\"Use of !important\", name.line, name.col, rule);\n            }\n        });\n\n        //report the results\n        parser.addListener(\"endstylesheet\", function(){\n            reporter.stat(\"important\", count);\n            if (count >= 10){\n                reporter.rollupError(\"Too many !important declarations (\" + count + \"), be careful with rule specificity\", rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: Don't use classes or IDs with elements (a.foo or a#foo).\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"overqualified-elements\",\n    name: \"Overqualified Elements\",\n    desc: \"Don't use classes or IDs with elements (a.foo or a#foo).\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            classes = {};\n            \n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                modifier,\n                i, j, k;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n\n                for (j=0; j < selector.parts.length; j++){\n                    part = selector.parts[j];\n                    if (part instanceof parserlib.css.SelectorPart){\n                        for (k=0; k < part.modifiers.length; k++){\n                            modifier = part.modifiers[k];\n                            if (part.elementName && modifier.type == \"id\"){\n                                reporter.warn(\"Element (\" + part + \") is overqualified, just use \" + modifier + \" without element name.\", part.line, part.col, rule);\n                            } else if (modifier.type == \"class\"){\n                                \n                                if (!classes[modifier]){\n                                    classes[modifier] = [];\n                                }\n                                classes[modifier].push({ modifier: modifier, part: part });\n                            }\n                        }\n                    }\n                }\n            }\n        });\n        \n        parser.addListener(\"endstylesheet\", function(){\n        \n            var prop;\n            for (prop in classes){\n                if (classes.hasOwnProperty(prop)){\n                \n                    //one use means that this is overqualified\n                    if (classes[prop].length == 1 && classes[prop][0].part.elementName){\n                        reporter.warn(\"Element (\" + classes[prop][0].part + \") is overqualified, just use \" + classes[prop][0].modifier + \" without element name.\", classes[prop][0].part.line, classes[prop][0].part.col, rule);\n                    }\n                }\n            }        \n        });\n    }\n\n});\n/*\n * Rule: Headings (h1-h6) should not be qualified (namespaced).\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"qualified-headings\",\n    name: \"Qualified Headings\",\n    desc: \"Headings should not be qualified (namespaced).\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                i, j;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n\n                for (j=0; j < selector.parts.length; j++){\n                    part = selector.parts[j];\n                    if (part instanceof parserlib.css.SelectorPart){\n                        if (part.elementName && /h[1-6]/.test(part.elementName.toString()) && j > 0){\n                            reporter.warn(\"Heading (\" + part.elementName + \") should not be qualified.\", part.line, part.col, rule);\n                        }\n                    }\n                }\n            }\n        });\n    }\n\n});\n/*\n * Rule: Selectors that look like regular expressions are slow and should be avoided.\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"regex-selectors\",\n    name: \"Regex Selectors\",\n    desc: \"Selectors that look like regular expressions are slow and should be avoided.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                modifier,\n                i, j, k;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n                for (j=0; j < selector.parts.length; j++){\n                    part = selector.parts[j];\n                    if (part instanceof parserlib.css.SelectorPart){\n                        for (k=0; k < part.modifiers.length; k++){\n                            modifier = part.modifiers[k];\n                            if (modifier.type == \"attribute\"){\n                                if (/([\\~\\|\\^\\$\\*]=)/.test(modifier)){\n                                    reporter.warn(\"Attribute selectors with \" + RegExp.$1 + \" are slow!\", modifier.line, modifier.col, rule);\n                                }\n                            }\n\n                        }\n                    }\n                }\n            }\n        });\n    }\n\n});\n/*\n * Rule: Total number of rules should not exceed x.\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"rules-count\",\n    name: \"Rules Count\",\n    desc: \"Track how many rules there are.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            count = 0;\n\n        //count each rule\n        parser.addListener(\"startrule\", function(){\n            count++;\n        });\n\n        parser.addListener(\"endstylesheet\", function(){\n            reporter.stat(\"rule-count\", count);\n        });\n    }\n\n});\n/*\n * Rule: Don't use text-indent for image replacement if you need to support rtl. \n * \n */\n/*\n * Should we be checking for rtl/ltr?\n */\n//Commented out due to lack of tests\n/*CSSLint.addRule({\n\n    //rule information\n    id: \"text-indent\",\n    name: \"Text Indent\",\n    desc: \"Checks for text indent less than -99px\",\n    browsers: \"All\",\n    \n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n    \n        //check for use of \"font-size\"\n        parser.addListener(\"property\", function(event){\n            var name = event.property,\n                value = event.value;\n\n            if (name == \"text-indent\" && value < -99){\n                reporter.warn(\"Negative text-indent doesn't work well with RTL. If you use text-indent for image replacement explicitly set text-direction for that item to ltr.\", name.line, name.col, rule);\n            }\n        });\n    }\n\n});*/\n/*\n * Rule: Headings (h1-h6) should be defined only once.\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"unique-headings\",\n    name: \"Unique Headings\",\n    desc: \"Headings should be defined only once.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        var headings =  {\n                h1: 0,\n                h2: 0,\n                h3: 0,\n                h4: 0,\n                h5: 0,\n                h6: 0\n            };\n\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                i;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n                part = selector.parts[selector.parts.length-1];\n\n                if (part.elementName && /(h[1-6])/.test(part.elementName.toString())){\n                    headings[RegExp.$1]++;\n                    if (headings[RegExp.$1] > 1) {\n                        reporter.warn(\"Heading (\" + part.elementName + \") has already been defined.\", part.line, part.col, rule);\n                    }\n                }\n            }\n        });\n    }\n\n});\n/*\n * Rule: When using a vendor-prefixed property, make sure to\n * include the standard one.\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"vendor-prefix\",\n    name: \"Vendor Prefix\",\n    desc: \"When using a vendor-prefixed property, make sure to include the standard one.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            properties,\n            num,\n            propertiesToCheck = {\n                \"-moz-border-radius\": \"border-radius\",\n                \"-webkit-border-radius\": \"border-radius\",\n                \"-webkit-border-top-left-radius\": \"border-top-left-radius\",\n                \"-webkit-border-top-right-radius\": \"border-top-right-radius\",\n                \"-webkit-border-bottom-left-radius\": \"border-bottom-left-radius\",\n                \"-webkit-border-bottom-right-radius\": \"border-bottom-right-radius\",\n                \"-moz-border-radius-topleft\": \"border-top-left-radius\",\n                \"-moz-border-radius-topright\": \"border-top-right-radius\",\n                \"-moz-border-radius-bottomleft\": \"border-bottom-left-radius\",\n                \"-moz-border-radius-bottomright\": \"border-bottom-right-radius\",\n                \"-moz-box-shadow\": \"box-shadow\",\n                \"-webkit-box-shadow\": \"box-shadow\",\n                \"-moz-transform\" : \"transform\",\n                \"-webkit-transform\" : \"transform\",\n                \"-o-transform\" : \"transform\",\n                \"-ms-transform\" : \"transform\",\n                \"-moz-box-sizing\" : \"box-sizing\",\n                \"-webkit-box-sizing\" : \"box-sizing\"\n            };\n\n        //event handler for beginning of rules\n        function startRule(){\n            properties = {};\n            num=1;        \n        }\n        \n        //event handler for end of rules\n        function endRule(event){\n            var prop,\n                i, len,\n                standard,\n                needed,\n                actual,\n                needsStandard = [];\n\n            for (prop in properties){\n                if (propertiesToCheck[prop]){\n                    needsStandard.push({ actual: prop, needed: propertiesToCheck[prop]});\n                }\n            }\n\n            for (i=0, len=needsStandard.length; i < len; i++){\n                needed = needsStandard[i].needed;\n                actual = needsStandard[i].actual;\n\n                if (!properties[needed]){               \n                    reporter.warn(\"Missing standard property '\" + needed + \"' to go along with '\" + actual + \"'.\", event.line, event.col, rule);\n                } else {\n                    //make sure standard property is last\n                    if (properties[needed][0].pos < properties[actual][0].pos){\n                        reporter.warn(\"Standard property '\" + needed + \"' should come after vendor-prefixed property '\" + actual + \"'.\", event.line, event.col, rule);\n                    }\n                }\n            }\n\n        }        \n        \n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text.toLowerCase();\n\n            if (!properties[name]){\n                properties[name] = [];\n            }\n\n            properties[name].push({ name: event.property, value : event.value, pos:num++ });\n        });\n\n        parser.addListener(\"endrule\", endRule);\n        parser.addListener(\"endfontface\", endRule);\n    }\n\n});\n/*\n * Rule: If an element has a width of 100%, be careful when placing within\n * an element that has padding. It may look strange.\n */\n//Commented out pending further review.\n/*CSSLint.addRule({\n\n    //rule information\n    id: \"width-100\",\n    name: \"Width 100%\",\n    desc: \"Be careful when using width: 100% on elements.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            width100,\n            boxsizing;\n\n        parser.addListener(\"startrule\", function(){\n            width100 = null;\n            boxsizing = false;\n        });\n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text.toLowerCase(),\n                value = event.value;\n\n            if (name == \"width\" && value == \"100%\"){\n                width100 = event.property;\n            } else if (name == \"box-sizing\" || /\\-(?:webkit|ms|moz)\\-box-sizing/.test(name)){  //means you know what you're doing\n                boxsizing = true;\n            }\n        });\n        \n        parser.addListener(\"endrule\", function(){\n            if (width100 && !boxsizing){\n                reporter.warn(\"Elements with a width of 100% may not appear as you expect inside of other elements.\", width100.line, width100.col, rule);\n            }\n        });\n    }\n\n});*/\n/*\n * Rule: You don't need to specify units when a value is 0.\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"zero-units\",\n    name: \"Zero Units\",\n    desc: \"You don't need to specify units when a value is 0.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        //count how many times \"float\" is used\n        parser.addListener(\"property\", function(event){\n            var parts = event.value.parts,\n                i = 0, \n                len = parts.length;\n\n            while(i < len){\n                if ((parts[i].units || parts[i].type == \"percentage\") && parts[i].value === 0){\n                    reporter.warn(\"Values of 0 shouldn't have units specified.\", parts[i].line, parts[i].col, rule);\n                }\n                i++;\n            }\n\n        });\n\n    }\n\n});\nCSSLint.addFormatter({\n    //format information\n    id: \"lint-xml\",\n    name: \"Lint XML format\",\n    \n    startFormat: function(){\n        return \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?><lint>\";\n    },\n\n    endFormat: function(){\n        return \"</lint>\";\n    },\n    \n    formatResults: function(results, filename) {\n        var messages = results.messages,\n            output = [];\n\n        var replaceDoubleQuotes = function(str) {\n            if (!str || str.constructor !== String) {\n                return \"\";\n            }\n            return str.replace(/\\\"/g, \"'\");\n        };\n\n        if (messages.length > 0) {\n            //rollups at the bottom\n            messages.sort(function (a, b) {\n                if (a.rollup && !b.rollup) {\n                    return 1;\n                } else if (!a.rollup && b.rollup) {\n                    return -1;\n                } else {\n                    return 0;\n                }\n            });\n        \n            output.push(\"<file name=\\\"\"+filename+\"\\\">\");\n            messages.forEach(function (message, i) {\n                if (message.rollup) {\n                    output.push(\"<issue severity=\\\"\" + message.type + \"\\\" reason=\\\"\" + replaceDoubleQuotes(message.message) + \"\\\" evidence=\\\"\" + replaceDoubleQuotes(message.evidence) + \"\\\"/>\");\n                } else {\n                    output.push(\"<issue line=\\\"\" + message.line + \"\\\" char=\\\"\" + message.col + \"\\\" severity=\\\"\" + message.type + \"\\\"\" +\n                        \" reason=\\\"\" + replaceDoubleQuotes(message.message) + \"\\\" evidence=\\\"\" + replaceDoubleQuotes(message.evidence) + \"\\\"/>\");\n                }\n            });\n            output.push(\"</file>\");\n        }\n\n        return output.join(\"\");\n    }\n});\nCSSLint.addFormatter({\n    //format information\n    id: \"text\",\n    name: \"Plain Text\",\n    \n    startFormat: function(){\n        return \"\";\n    },\n    \n    endFormat: function(){\n        return \"\";\n    },\n\n    formatResults: function(results, filename) {\n        var messages = results.messages;\n        if (messages.length === 0) {\n            return \"\\n\\ncsslint: No errors in \" + filename + \".\";\n        }\n        \n        output = \"\\n\\ncsslint: There are \" + messages.length  +  \" problems in \" + filename + \".\";\n        var pos = filename.lastIndexOf(\"/\"),\n            shortFilename = filename;\n\n        if (pos == -1){\n            pos = filename.lastIndexOf(\"\\\\\");       \n        }\n        if (pos > -1){\n            shortFilename = filename.substring(pos+1);\n        }\n\n        //rollups at the bottom\n        messages.sort(function (a, b){\n            if (a.rollup && !b.rollup){\n                return 1;\n            } else if (!a.rollup && b.rollup){\n                return -1;\n            } else {\n                return 0;\n            }\n        });\n\n        messages.forEach(function (message, i) {\n            output = output + \"\\n\\n\" + shortFilename;\n            if (message.rollup) {\n                output += \"\\n\" + (i+1) + \": \" + message.type;\n                output += \"\\n\" + message.message;\n            } else {\n                output += \"\\n\" + (i+1) + \": \" + message.type + \" at line \" + message.line + \", col \" + message.col;\n                output += \"\\n\" + message.message;\n                output += \"\\n\" + message.evidence;\n            }\n        });\n    \n        return output;\n    }\n});\n\nreturn CSSLint;\n})();\n//print for rhino and nodejs\nif(typeof print == \"undefined\") {\n    var print = console.log;\n}\n\n//readFile for rhino and nodejs\nif(typeof readFile == \"undefined\") {\n    var readFile = function(filepath) {\n        var fs = require(\"fs\");\n        return fs.readFileSync(filepath, \"utf-8\");\n    }\n}\n\n//filter messages by type\nvar pluckByType = function(messages, type){\n    return messages.filter(function(message) {\n        return message.type === type;\n    });\n};\n\nfunction gatherRules(options){\n    var ruleset;\n    \n    if (options.rules){\n        ruleset = {};\n        options.rules.split(\",\").forEach(function(value){\n            ruleset[value] = 1;\n        });\n    }\n    \n    return ruleset;\n}\n\n//process a list of files, return 1 if one or more error occurred\nvar processFile = function(filename, options) {\n    var input = readFile(filename),\n        result = CSSLint.verify(input, gatherRules(options)),\n        formatId = options.format || \"text\",\n        messages = result.messages || [],\n        exitCode = 0;\n\n    if (!input) {\n        print(\"csslint: Could not read file data in \" + filename + \". Is the file empty?\");\n        exitCode = 1;\n    } else {\n        print(CSSLint.getFormatter(formatId).formatResults(result, filename, formatId));\n\n        if (messages.length > 0 && pluckByType(messages, 'error').length > 0) {\n            exitCode = 1;\n        }\n    }\n    \n    return exitCode;\n};\n\n//output CLI help screen\nfunction outputHelp(){\n    print([\n        \"\\nUsage: csslint-rhino.js [options]* [file|dir]*\",\n        \" \",\n        \"Global Options\",\n        \"  --help                 Displays this information.\",\n        \"  --rules=<rule[,rule]+> Indicate which rules to include.\",\n        \"  --format=<format>      Indicate which format to use for output.\",\n        \"  --version              Outputs the current version number.\"\n    ].join(\"\\n\") + \"\\n\\n\");\n}\n\nfunction processFiles(files, options){\n    var exitCode = 0,\n        formatId = options.format || \"text\",\n        formatter;\n    if (!files.length) {\n        print(\"No files specified.\");\n        exitCode = 1;\n    } else {\n        if (!CSSLint.hasFormat(formatId)){\n            print(\"csslint: Unknown format '\" + formatId + \"'. Cannot proceed.\");\n            exitCode = 1; \n        } else {\n            formatter = CSSLint.getFormatter(formatId);\n            print(formatter.startFormat());\n            exitCode = files.some(function(file){\n                processFile(file,options);\n            });\n            print(formatter.endFormat());\n        }\n    }\n    return exitCode;\n}\n/*\n * CSSLint Rhino Command Line Interface\n */\n\nimportPackage(java.io);\n\n//-----------------------------------------------------------------------------\n// Helper Functions\n//-----------------------------------------------------------------------------\n\nfunction getFiles(dir) {\n    var files = [];\n\n    var traverse = function (dir) {\n        var dirList = dir.listFiles();\n        dirList.forEach(function (file) {\n            if (/\\.css$/.test(file)) {\n                files.push(file);\n            } else if (file.isDirectory()) {\n                traverse(file);\n            }\n        });\n    };\n\n    traverse(dir);\n\n    return files;\n};\n\n//-----------------------------------------------------------------------------\n// Process command line\n//-----------------------------------------------------------------------------\n\nvar args     = Array.prototype.slice.call(arguments),\n    argName,\n    arg      = args.shift(),\n    options  = {},\n    files    = [];\n\nwhile(arg){\n    if (arg.indexOf(\"--\") == 0){\n        argName = arg.substring(2);\n        options[argName] = true;\n        \n        if (argName.indexOf(\"rules=\") > -1){\n            options.rules = argName.substring(argName.indexOf(\"=\") + 1);\n        } else if (argName.indexOf(\"format=\") > -1) {\n            options.format = argName.substring(argName.indexOf(\"=\") + 1);\n        }\n    } else {\n        var curFile = new File(arg);\n        \n        //see if it's a directory or a file\n        if (curFile.isDirectory()){\n            files = files.concat(getFiles(arg));\n        } else {\n            files.push(arg);\n        }\n    }\n    arg = args.shift();\n}\n\nif (options.help || arguments.length == 0){\n    outputHelp();\n    quit(0);\n}\n\nif (options.version){\n    print(\"v\" + CSSLint.version);\n    quit(0);\n}\n\n\n\nquit(processFiles(files,options));\n"
  },
  {
    "path": "build/tools/fulljshint.js",
    "content": "/*\n * JSHint, by JSHint Community.\n *\n * Licensed under the same slightly modified MIT license that JSLint is.\n * It stops evil-doers everywhere.\n *\n * JSHint is a derivative work of JSLint:\n *\n *   Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)\n *\n *   Permission is hereby granted, free of charge, to any person obtaining\n *   a copy of this software and associated documentation files (the \"Software\"),\n *   to deal in the Software without restriction, including without limitation\n *   the rights to use, copy, modify, merge, publish, distribute, sublicense,\n *   and/or sell copies of the Software, and to permit persons to whom\n *   the Software is furnished to do so, subject to the following conditions:\n *\n *   The above copyright notice and this permission notice shall be included\n *   in all copies or substantial portions of the Software.\n *\n *   The Software shall be used for Good, not Evil.\n *\n *   THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n *   DEALINGS IN THE SOFTWARE.\n *\n * JSHint was forked from 2010-12-16 edition of JSLint.\n *\n */\n\n/*\n JSHINT is a global function. It takes two parameters.\n\n     var myResult = JSHINT(source, option);\n\n The first parameter is either a string or an array of strings. If it is a\n string, it will be split on '\\n' or '\\r'. If it is an array of strings, it\n is assumed that each string represents one line. The source can be a\n JavaScript text, or HTML text, or a JSON text, or a CSS text.\n\n The second parameter is an optional object of options which control the\n operation of JSHINT. Most of the options are booleans: They are all\n optional and have a default value of false. One of the options, predef,\n can be an array of names, which will be used to declare global variables,\n or an object whose keys are used as global names, with a boolean value\n that determines if they are assignable.\n\n If it checks out, JSHINT returns true. Otherwise, it returns false.\n\n If false, you can inspect JSHINT.errors to find out the problems.\n JSHINT.errors is an array of objects containing these members:\n\n {\n     line      : The line (relative to 0) at which the lint was found\n     character : The character (relative to 0) at which the lint was found\n     reason    : The problem\n     evidence  : The text line in which the problem occurred\n     raw       : The raw message before the details were inserted\n     a         : The first detail\n     b         : The second detail\n     c         : The third detail\n     d         : The fourth detail\n }\n\n If a fatal error was found, a null will be the last element of the\n JSHINT.errors array.\n\n You can request a Function Report, which shows all of the functions\n and the parameters and vars that they use. This can be used to find\n implied global variables and other problems. The report is in HTML and\n can be inserted in an HTML <body>.\n\n     var myReport = JSHINT.report(limited);\n\n If limited is true, then the report will be limited to only errors.\n\n You can request a data structure which contains JSHint's results.\n\n     var myData = JSHINT.data();\n\n It returns a structure with this form:\n\n {\n     errors: [\n         {\n             line: NUMBER,\n             character: NUMBER,\n             reason: STRING,\n             evidence: STRING\n         }\n     ],\n     functions: [\n         name: STRING,\n         line: NUMBER,\n         last: NUMBER,\n         param: [\n             STRING\n         ],\n         closure: [\n             STRING\n         ],\n         var: [\n             STRING\n         ],\n         exception: [\n             STRING\n         ],\n         outer: [\n             STRING\n         ],\n         unused: [\n             STRING\n         ],\n         global: [\n             STRING\n         ],\n         label: [\n             STRING\n         ]\n     ],\n     globals: [\n         STRING\n     ],\n     member: {\n         STRING: NUMBER\n     },\n     unuseds: [\n         {\n             name: STRING,\n             line: NUMBER\n         }\n     ],\n     implieds: [\n         {\n             name: STRING,\n             line: NUMBER\n         }\n     ],\n     urls: [\n         STRING\n     ],\n     json: BOOLEAN\n }\n\n Empty arrays will not be included.\n\n*/\n\n/*jshint\n evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true\n*/\n\n/*members \"\\b\", \"\\t\", \"\\n\", \"\\f\", \"\\r\", \"!=\", \"!==\", \"\\\"\", \"%\",\n \"(begin)\", \"(breakage)\", \"(context)\", \"(error)\", \"(global)\",\n \"(identifier)\", \"(last)\", \"(line)\", \"(loopage)\", \"(name)\", \"(onevar)\",\n \"(params)\", \"(scope)\", \"(statement)\", \"(verb)\", \"*\", \"+\", \"++\", \"-\",\n \"--\", \"\\/\", \"<\", \"<=\", \"==\", \"===\", \">\", \">=\", ADSAFE, __filename, __dirname,\n ActiveXObject, Array, Boolean, Buffer, COM, CScript, Canvas, CustomAnimation,\n Date, Debug, E, Enumerator, Error, EvalError, FadeAnimation, Flash,\n FormField, Frame, Function, HotKey, Image, JSON, LN10, LN2, LOG10E,\n LOG2E, MAX_VALUE, MIN_VALUE, Math, MenuItem, MoveAnimation,\n NEGATIVE_INFINITY, Number, Object, Option, PI, POSITIVE_INFINITY, Point,\n RangeError, Rectangle, ReferenceError, RegExp, ResizeAnimation,\n RotateAnimation, SQRT1_2, SQRT2, ScrollBar, String, Style, SyntaxError,\n System, Text, TextArea, Timer, TypeError, URIError, URL, VBArray,\n WScript, Web, Window, XMLDOM, XMLHttpRequest, \"\\\\\", a, abbr, acronym,\n activeborder, activecaption, addEventListener, address, adsafe, alert,\n aliceblue, all, animator, antiquewhite, appleScript, applet, apply,\n approved, appworkspace, aqua, aquamarine, area, arguments, arity,\n article, aside, audio, autocomplete, azure, b, background,\n \"background-attachment\", \"background-color\", \"background-image\",\n \"background-position\", \"background-repeat\", base, bdo, beep, beige, big,\n bisque, bitwise, black, blanchedalmond, block, blockquote, blue,\n blueviolet, blur, body, border, \"border-bottom\", \"border-bottom-color\",\n \"border-bottom-style\", \"border-bottom-width\", \"border-collapse\",\n \"border-color\", \"border-left\", \"border-left-color\", \"border-left-style\",\n \"border-left-width\", \"border-right\", \"border-right-color\",\n \"border-right-style\", \"border-right-width\", \"border-spacing\",\n \"border-style\", \"border-top\", \"border-top-color\", \"border-top-style\",\n \"border-top-width\", \"border-width\", bottom, boss, br, braille, brown, browser,\n burlywood, button, buttonface, buttonhighlight, buttonshadow,\n buttontext, bytesToUIString, c, cadetblue, call, callee, caller, canvas,\n cap, caption, \"caption-side\", captiontext, cases, center, charAt,\n charCodeAt, character, chartreuse, chocolate, chooseColor, chooseFile,\n chooseFolder, cite, clear, clearInterval, clearTimeout, clip, close,\n closeWidget, closed, closure, cm, code, col, colgroup, color, command,\n comment, condition, confirm, console, constructor, content,\n convertPathToHFS, convertPathToPlatform, coral, cornflowerblue,\n cornsilk, \"counter-increment\", \"counter-reset\", create, crimson, css, curly,\n cursor, cyan, d, darkblue, darkcyan, darkgoldenrod, darkgray, darkgreen,\n darkkhaki, darkmagenta, darkolivegreen, darkorange, darkorchid, darkred,\n darksalmon, darkseagreen, darkslateblue, darkslategray, darkturquoise,\n darkviolet, data, datalist, dd, debug, decodeURI, decodeURIComponent,\n deeppink, deepskyblue, defaultStatus, defineClass, del, deserialize,\n details, devel, dfn, dialog, dimgray, dir, direction, display, div, dl,\n document, dodgerblue, dt, edition, else, em, embed, embossed, empty,\n \"empty-cells\", encodeURI, encodeURIComponent, entityify, eqeqeq, errors,\n es5, escape, eval, event, evidence, evil, ex, exception, exec, exps, exports,\n fieldset, figure, filesystem, firebrick, first, float, floor,\n floralwhite, focus, focusWidget, font, \"font-family\", \"font-size\",\n \"font-size-adjust\", \"font-stretch\", \"font-style\", \"font-variant\",\n \"font-weight\", footer, forestgreen, forin, form, fragment, frame,\n frames, frameset, from, fromCharCode, fuchsia, fud, funct, function,\n functions, g, gainsboro, gc, getComputedStyle, ghostwhite, GLOBAL, global,\n globals, gold, goldenrod, gray, graytext, green, greenyellow, h1, h2,\n h3, h4, h5, h6, handheld, hasOwnProperty, head, header, height, help,\n hgroup, highlight, highlighttext, history, honeydew, hotpink, hr,\n \"hta:application\", html, i, iTunes, id, identifier, iframe, img, immed,\n implieds, in, inactiveborder, inactivecaption, inactivecaptiontext,\n include, indent, indexOf, indianred, indigo, infobackground, infotext,\n init, input, ins, isAlpha, isApplicationRunning, isArray, isDigit,\n isFinite, isNaN, ivory, join, jshint, JSHINT, json, kbd, keygen, keys, khaki,\n konfabulatorVersion, label, labelled, lang, last, lavender,\n lavenderblush, lawngreen, laxbreak, lbp, led, left, legend,\n lemonchiffon, length, \"letter-spacing\", li, lib, lightblue, lightcoral,\n lightcyan, lightgoldenrodyellow, lightgreen, lightpink, lightsalmon,\n lightseagreen, lightskyblue, lightslategray, lightsteelblue,\n lightyellow, lime, limegreen, line, \"line-height\", linen, link,\n \"list-style\", \"list-style-image\", \"list-style-position\",\n \"list-style-type\", load, loadClass, location, log, m, magenta, map,\n margin, \"margin-bottom\", \"margin-left\", \"margin-right\", \"margin-top\",\n mark, \"marker-offset\", maroon, match, \"max-height\", \"max-width\", maxerr,\n maxlen, md5, mediumaquamarine, mediumblue, mediumorchid, mediumpurple,\n mediumseagreen, mediumslateblue, mediumspringgreen, mediumturquoise,\n mediumvioletred, member, menu, menutext, message, meta, meter,\n midnightblue, \"min-height\", \"min-width\", mintcream, mistyrose, mm,\n moccasin, module, moveBy, moveTo, name, nav, navajowhite, navigator, navy, new,\n newcap, noarg, node, noempty, noframes, nomen, nonew, noscript, nud, object, ol,\n oldlace, olive, olivedrab, on, onbeforeunload, onblur, onerror, onevar,\n onfocus, onload, onresize, onunload, opacity, open, openURL, opener, opera,\n optgroup, option, orange, orangered, orchid, outer, outline, \"outline-color\",\n \"outline-style\", \"outline-width\", output, overflow, \"overflow-x\",\n \"overflow-y\", p, padding, \"padding-bottom\", \"padding-left\",\n \"padding-right\", \"padding-top\", \"page-break-after\", \"page-break-before\",\n palegoldenrod, palegreen, paleturquoise, palevioletred, papayawhip,\n param, parent, parseFloat, parseInt, passfail, pc, peachpuff, peru,\n pink, play, plum, plusplus, pop, popupMenu, position, powderblue, pre,\n predef, preferenceGroups, preferences, print, process, progress, projection,\n prompt, prototype, pt, purple, push, px, q, quit, quotes, random, range,\n raw, reach, readFile, readUrl, reason, red, regexp, reloadWidget,\n removeEventListener, replace, report, require, reserved, resizeBy, resizeTo,\n resolvePath, resumeUpdates, rhino, right, rosybrown, royalblue, rp, rt,\n ruby, runCommand, runCommandInBg, saddlebrown, safe, salmon, samp,\n sandybrown, saveAs, savePreferences, screen, script, scroll, scrollBy,\n scrollTo, scrollbar, seagreen, seal, search, seashell, section, select,\n serialize, setInterval, setTimeout, shift, showWidgetPreferences,\n sienna, silver, skyblue, slateblue, slategray, sleep, slice, small,\n snow, sort, source, span, spawn, speak, speech, split, springgreen, src,\n stack, status, steelblue, strict, strong, style, styleproperty, sub,\n substr, sup, supplant, suppressUpdates, sync, system, table,\n \"table-layout\", tan, tbody, td, teal, tellWidget, test, \"text-align\",\n \"text-decoration\", \"text-indent\", \"text-shadow\", \"text-transform\",\n textarea, tfoot, th, thead, thistle, threeddarkshadow, threedface,\n threedhighlight, threedlightshadow, threedshadow, time, title,\n toLowerCase, toString, toUpperCase, toint32, token, tomato, top, tr, tt,\n tty, turquoise, tv, type, u, ul, undef, unescape, \"unicode-bidi\",\n unused, unwatch, updateNow, urls, value, valueOf, var, version,\n \"vertical-align\", video, violet, visibility, watch, wheat, white,\n \"white-space\", whitesmoke, widget, width, window, windowframe, windows,\n windowtext, \"word-spacing\", \"word-wrap\", yahooCheckLogin, yahooLogin,\n yahooLogout, yellow, yellowgreen, \"z-index\"\n*/\n\n/*global exports: false */\n\n// We build the application inside a function so that we produce only a single\n// global variable. That function will be invoked immediately, and its return\n// value is the JSHINT function itself.\n\nvar JSHINT = (function () {\n    \"use strict\";\n\n    var adsafe_id,      // The widget's ADsafe id.\n        adsafe_may,     // The widget may load approved scripts.\n        adsafe_went,    // ADSAFE.go has been called.\n        anonname,       // The guessed name for anonymous functions.\n        approved,       // ADsafe approved urls.\n\n// These are operators that should not be used with the ! operator.\n\n        bang = {\n            '<'  : true,\n            '<=' : true,\n            '==' : true,\n            '===': true,\n            '!==': true,\n            '!=' : true,\n            '>'  : true,\n            '>=' : true,\n            '+'  : true,\n            '-'  : true,\n            '*'  : true,\n            '/'  : true,\n            '%'  : true\n        },\n\n// These are property names that should not be permitted in the safe subset.\n\n        banned = { // the member names that ADsafe prohibits.\n            'arguments'     : true,\n            callee          : true,\n            caller          : true,\n            constructor     : true,\n            'eval'          : true,\n            prototype       : true,\n            stack           : true,\n            unwatch         : true,\n            valueOf         : true,\n            watch           : true\n        },\n\n\n// These are the JSHint boolean options.\n\n        boolOptions = {\n            adsafe     : true, // if ADsafe should be enforced\n            bitwise    : true, // if bitwise operators should not be allowed\n            boss       : true, // if assignments inside if/for/while/do should be allowed\n            browser    : true, // if the standard browser globals should be predefined\n            cap        : true, // if upper case HTML should be allowed\n            css        : true, // if CSS workarounds should be tolerated\n            curly      : true, // if curly braces around blocks should be required (even in if/for/while)\n            debug      : true, // if debugger statements should be allowed\n            devel      : true, // if logging should be allowed (console, alert, etc.)\n            eqeqeq     : true, // if === should be required\n            es5        : true, // if ES5 syntax should be allowed\n            evil       : true, // if eval should be allowed\n            forin      : true, // if for in statements must filter\n            fragment   : true, // if HTML fragments should be allowed\n            immed      : true, // if immediate invocations must be wrapped in parens\n            laxbreak   : true, // if line breaks should not be checked\n            newcap     : true, // if constructor names must be capitalized\n            noarg      : true, // if arguments.caller and arguments.callee should be disallowed\n            node       : true, // if the Node.js environment globals should be predefined\n            noempty    : true, // if empty blocks should be disallowed\n            nonew      : true, // if using `new` for side-effects should be disallowed\n            nomen      : true, // if names should be checked\n            on         : true, // if HTML event handlers should be allowed\n            onevar     : true, // if only one var statement per function should be allowed\n            passfail   : true, // if the scan should stop on first error\n            plusplus   : true, // if increment/decrement should not be allowed\n            regexp     : true, // if the . should not be allowed in regexp literals\n            rhino      : true, // if the Rhino environment globals should be predefined\n            undef      : true, // if variables should be declared before used\n            safe       : true, // if use of some browser features should be restricted\n            windows    : true, // if MS Windows-specigic globals should be predefined\n            strict     : true, // require the \"use strict\"; pragma\n            sub        : true, // if all forms of subscript notation are tolerated\n            white      : true, // if strict whitespace rules apply\n            widget     : true  // if the Yahoo Widgets globals should be predefined\n        },\n\n// browser contains a set of global names which are commonly provided by a\n// web browser environment.\n\n        browser = {\n            addEventListener: false,\n            blur            : false,\n            clearInterval   : false,\n            clearTimeout    : false,\n            close           : false,\n            closed          : false,\n            defaultStatus   : false,\n            document        : false,\n            event           : false,\n            focus           : false,\n            frames          : false,\n            getComputedStyle: false,\n            history         : false,\n            Image           : false,\n            length          : false,\n            location        : false,\n            moveBy          : false,\n            moveTo          : false,\n            name            : false,\n            navigator       : false,\n            onbeforeunload  : true,\n            onblur          : true,\n            onerror         : true,\n            onfocus         : true,\n            onload          : true,\n            onresize        : true,\n            onunload        : true,\n            open            : false,\n            opener          : false,\n            Option          : false,\n            parent          : false,\n            print           : false,\n            removeEventListener: false,\n            resizeBy        : false,\n            resizeTo        : false,\n            screen          : false,\n            scroll          : false,\n            scrollBy        : false,\n            scrollTo        : false,\n            setInterval     : false,\n            setTimeout      : false,\n            status          : false,\n            top             : false,\n            window          : false,\n            XMLHttpRequest  : false\n        },\n\n        cssAttributeData,\n        cssAny,\n\n        cssColorData = {\n            \"aliceblue\"             : true,\n            \"antiquewhite\"          : true,\n            \"aqua\"                  : true,\n            \"aquamarine\"            : true,\n            \"azure\"                 : true,\n            \"beige\"                 : true,\n            \"bisque\"                : true,\n            \"black\"                 : true,\n            \"blanchedalmond\"        : true,\n            \"blue\"                  : true,\n            \"blueviolet\"            : true,\n            \"brown\"                 : true,\n            \"burlywood\"             : true,\n            \"cadetblue\"             : true,\n            \"chartreuse\"            : true,\n            \"chocolate\"             : true,\n            \"coral\"                 : true,\n            \"cornflowerblue\"        : true,\n            \"cornsilk\"              : true,\n            \"crimson\"               : true,\n            \"cyan\"                  : true,\n            \"darkblue\"              : true,\n            \"darkcyan\"              : true,\n            \"darkgoldenrod\"         : true,\n            \"darkgray\"              : true,\n            \"darkgreen\"             : true,\n            \"darkkhaki\"             : true,\n            \"darkmagenta\"           : true,\n            \"darkolivegreen\"        : true,\n            \"darkorange\"            : true,\n            \"darkorchid\"            : true,\n            \"darkred\"               : true,\n            \"darksalmon\"            : true,\n            \"darkseagreen\"          : true,\n            \"darkslateblue\"         : true,\n            \"darkslategray\"         : true,\n            \"darkturquoise\"         : true,\n            \"darkviolet\"            : true,\n            \"deeppink\"              : true,\n            \"deepskyblue\"           : true,\n            \"dimgray\"               : true,\n            \"dodgerblue\"            : true,\n            \"firebrick\"             : true,\n            \"floralwhite\"           : true,\n            \"forestgreen\"           : true,\n            \"fuchsia\"               : true,\n            \"gainsboro\"             : true,\n            \"ghostwhite\"            : true,\n            \"gold\"                  : true,\n            \"goldenrod\"             : true,\n            \"gray\"                  : true,\n            \"green\"                 : true,\n            \"greenyellow\"           : true,\n            \"honeydew\"              : true,\n            \"hotpink\"               : true,\n            \"indianred\"             : true,\n            \"indigo\"                : true,\n            \"ivory\"                 : true,\n            \"khaki\"                 : true,\n            \"lavender\"              : true,\n            \"lavenderblush\"         : true,\n            \"lawngreen\"             : true,\n            \"lemonchiffon\"          : true,\n            \"lightblue\"             : true,\n            \"lightcoral\"            : true,\n            \"lightcyan\"             : true,\n            \"lightgoldenrodyellow\"  : true,\n            \"lightgreen\"            : true,\n            \"lightpink\"             : true,\n            \"lightsalmon\"           : true,\n            \"lightseagreen\"         : true,\n            \"lightskyblue\"          : true,\n            \"lightslategray\"        : true,\n            \"lightsteelblue\"        : true,\n            \"lightyellow\"           : true,\n            \"lime\"                  : true,\n            \"limegreen\"             : true,\n            \"linen\"                 : true,\n            \"magenta\"               : true,\n            \"maroon\"                : true,\n            \"mediumaquamarine\"      : true,\n            \"mediumblue\"            : true,\n            \"mediumorchid\"          : true,\n            \"mediumpurple\"          : true,\n            \"mediumseagreen\"        : true,\n            \"mediumslateblue\"       : true,\n            \"mediumspringgreen\"     : true,\n            \"mediumturquoise\"       : true,\n            \"mediumvioletred\"       : true,\n            \"midnightblue\"          : true,\n            \"mintcream\"             : true,\n            \"mistyrose\"             : true,\n            \"moccasin\"              : true,\n            \"navajowhite\"           : true,\n            \"navy\"                  : true,\n            \"oldlace\"               : true,\n            \"olive\"                 : true,\n            \"olivedrab\"             : true,\n            \"orange\"                : true,\n            \"orangered\"             : true,\n            \"orchid\"                : true,\n            \"palegoldenrod\"         : true,\n            \"palegreen\"             : true,\n            \"paleturquoise\"         : true,\n            \"palevioletred\"         : true,\n            \"papayawhip\"            : true,\n            \"peachpuff\"             : true,\n            \"peru\"                  : true,\n            \"pink\"                  : true,\n            \"plum\"                  : true,\n            \"powderblue\"            : true,\n            \"purple\"                : true,\n            \"red\"                   : true,\n            \"rosybrown\"             : true,\n            \"royalblue\"             : true,\n            \"saddlebrown\"           : true,\n            \"salmon\"                : true,\n            \"sandybrown\"            : true,\n            \"seagreen\"              : true,\n            \"seashell\"              : true,\n            \"sienna\"                : true,\n            \"silver\"                : true,\n            \"skyblue\"               : true,\n            \"slateblue\"             : true,\n            \"slategray\"             : true,\n            \"snow\"                  : true,\n            \"springgreen\"           : true,\n            \"steelblue\"             : true,\n            \"tan\"                   : true,\n            \"teal\"                  : true,\n            \"thistle\"               : true,\n            \"tomato\"                : true,\n            \"turquoise\"             : true,\n            \"violet\"                : true,\n            \"wheat\"                 : true,\n            \"white\"                 : true,\n            \"whitesmoke\"            : true,\n            \"yellow\"                : true,\n            \"yellowgreen\"           : true,\n\n            \"activeborder\"          : true,\n            \"activecaption\"         : true,\n            \"appworkspace\"          : true,\n            \"background\"            : true,\n            \"buttonface\"            : true,\n            \"buttonhighlight\"       : true,\n            \"buttonshadow\"          : true,\n            \"buttontext\"            : true,\n            \"captiontext\"           : true,\n            \"graytext\"              : true,\n            \"highlight\"             : true,\n            \"highlighttext\"         : true,\n            \"inactiveborder\"        : true,\n            \"inactivecaption\"       : true,\n            \"inactivecaptiontext\"   : true,\n            \"infobackground\"        : true,\n            \"infotext\"              : true,\n            \"menu\"                  : true,\n            \"menutext\"              : true,\n            \"scrollbar\"             : true,\n            \"threeddarkshadow\"      : true,\n            \"threedface\"            : true,\n            \"threedhighlight\"       : true,\n            \"threedlightshadow\"     : true,\n            \"threedshadow\"          : true,\n            \"window\"                : true,\n            \"windowframe\"           : true,\n            \"windowtext\"            : true\n        },\n\n        cssBorderStyle,\n        cssBreak,\n\n        cssLengthData = {\n            '%': true,\n            'cm': true,\n            'em': true,\n            'ex': true,\n            'in': true,\n            'mm': true,\n            'pc': true,\n            'pt': true,\n            'px': true\n        },\n\n        cssMedia,\n        cssOverflow,\n\n        devel = {\n            alert           : false,\n            confirm         : false,\n            console         : false,\n            Debug           : false,\n            opera           : false,\n            prompt          : false\n        },\n\n        escapes = {\n            '\\b': '\\\\b',\n            '\\t': '\\\\t',\n            '\\n': '\\\\n',\n            '\\f': '\\\\f',\n            '\\r': '\\\\r',\n            '\"' : '\\\\\"',\n            '/' : '\\\\/',\n            '\\\\': '\\\\\\\\'\n        },\n\n        funct,          // The current function\n\n        functionicity = [\n            'closure', 'exception', 'global', 'label',\n            'outer', 'unused', 'var'\n        ],\n\n        functions,      // All of the functions\n\n        global,         // The global scope\n        htmltag = {\n            a:        {},\n            abbr:     {},\n            acronym:  {},\n            address:  {},\n            applet:   {},\n            area:     {empty: true, parent: ' map '},\n            article:  {},\n            aside:    {},\n            audio:    {},\n            b:        {},\n            base:     {empty: true, parent: ' head '},\n            bdo:      {},\n            big:      {},\n            blockquote: {},\n            body:     {parent: ' html noframes '},\n            br:       {empty: true},\n            button:   {},\n            canvas:   {parent: ' body p div th td '},\n            caption:  {parent: ' table '},\n            center:   {},\n            cite:     {},\n            code:     {},\n            col:      {empty: true, parent: ' table colgroup '},\n            colgroup: {parent: ' table '},\n            command:  {parent: ' menu '},\n            datalist: {},\n            dd:       {parent: ' dl '},\n            del:      {},\n            details:  {},\n            dialog:   {},\n            dfn:      {},\n            dir:      {},\n            div:      {},\n            dl:       {},\n            dt:       {parent: ' dl '},\n            em:       {},\n            embed:    {},\n            fieldset: {},\n            figure:   {},\n            font:     {},\n            footer:   {},\n            form:     {},\n            frame:    {empty: true, parent: ' frameset '},\n            frameset: {parent: ' html frameset '},\n            h1:       {},\n            h2:       {},\n            h3:       {},\n            h4:       {},\n            h5:       {},\n            h6:       {},\n            head:     {parent: ' html '},\n            header:   {},\n            hgroup:   {},\n            hr:       {empty: true},\n            'hta:application':\n                      {empty: true, parent: ' head '},\n            html:     {parent: '*'},\n            i:        {},\n            iframe:   {},\n            img:      {empty: true},\n            input:    {empty: true},\n            ins:      {},\n            kbd:      {},\n            keygen:   {},\n            label:    {},\n            legend:   {parent: ' details fieldset figure '},\n            li:       {parent: ' dir menu ol ul '},\n            link:     {empty: true, parent: ' head '},\n            map:      {},\n            mark:     {},\n            menu:     {},\n            meta:     {empty: true, parent: ' head noframes noscript '},\n            meter:    {},\n            nav:      {},\n            noframes: {parent: ' html body '},\n            noscript: {parent: ' body head noframes '},\n            object:   {},\n            ol:       {},\n            optgroup: {parent: ' select '},\n            option:   {parent: ' optgroup select '},\n            output:   {},\n            p:        {},\n            param:    {empty: true, parent: ' applet object '},\n            pre:      {},\n            progress: {},\n            q:        {},\n            rp:       {},\n            rt:       {},\n            ruby:     {},\n            samp:     {},\n            script:   {empty: true, parent: ' body div frame head iframe p pre span '},\n            section:  {},\n            select:   {},\n            small:    {},\n            span:     {},\n            source:   {},\n            strong:   {},\n            style:    {parent: ' head ', empty: true},\n            sub:      {},\n            sup:      {},\n            table:    {},\n            tbody:    {parent: ' table '},\n            td:       {parent: ' tr '},\n            textarea: {},\n            tfoot:    {parent: ' table '},\n            th:       {parent: ' tr '},\n            thead:    {parent: ' table '},\n            time:     {},\n            title:    {parent: ' head '},\n            tr:       {parent: ' table tbody thead tfoot '},\n            tt:       {},\n            u:        {},\n            ul:       {},\n            'var':    {},\n            video:    {}\n        },\n\n        ids,            // HTML ids\n        implied,        // Implied globals\n        inblock,\n        indent,\n        jsonmode,\n        lines,\n        lookahead,\n        member,\n        membersOnly,\n        nexttoken,\n\n        node = {\n            __filename  : false,\n            __dirname   : false,\n            Buffer      : false,\n            GLOBAL      : false,\n            global      : false,\n            module      : false,\n            process     : false,\n            require     : false\n        },\n\n        noreach,\n        option,\n        predefined,     // Global variables defined by option\n        prereg,\n        prevtoken,\n\n        rhino = {\n            defineClass : false,\n            deserialize : false,\n            gc          : false,\n            help        : false,\n            load        : false,\n            loadClass   : false,\n            print       : false,\n            quit        : false,\n            readFile    : false,\n            readUrl     : false,\n            runCommand  : false,\n            seal        : false,\n            serialize   : false,\n            spawn       : false,\n            sync        : false,\n            toint32     : false,\n            version     : false\n        },\n\n        scope,      // The current scope\n        src,\n        stack,\n\n// standard contains the global names that are provided by the\n// ECMAScript standard.\n\n        standard = {\n            Array               : false,\n            Boolean             : false,\n            Date                : false,\n            decodeURI           : false,\n            decodeURIComponent  : false,\n            encodeURI           : false,\n            encodeURIComponent  : false,\n            Error               : false,\n            'eval'              : false,\n            EvalError           : false,\n            Function            : false,\n            hasOwnProperty      : false,\n            isFinite            : false,\n            isNaN               : false,\n            JSON                : false,\n            Math                : false,\n            Number              : false,\n            Object              : false,\n            parseInt            : false,\n            parseFloat          : false,\n            RangeError          : false,\n            ReferenceError      : false,\n            RegExp              : false,\n            String              : false,\n            SyntaxError         : false,\n            TypeError           : false,\n            URIError            : false\n        },\n\n        standard_member = {\n            E                   : true,\n            LN2                 : true,\n            LN10                : true,\n            LOG2E               : true,\n            LOG10E              : true,\n            MAX_VALUE           : true,\n            MIN_VALUE           : true,\n            NEGATIVE_INFINITY   : true,\n            PI                  : true,\n            POSITIVE_INFINITY   : true,\n            SQRT1_2             : true,\n            SQRT2               : true\n        },\n\n        strict_mode,\n        syntax = {},\n        tab,\n        token,\n        urls,\n        warnings,\n\n// widget contains the global names which are provided to a Yahoo\n// (fna Konfabulator) widget.\n\n        widget = {\n            alert                   : true,\n            animator                : true,\n            appleScript             : true,\n            beep                    : true,\n            bytesToUIString         : true,\n            Canvas                  : true,\n            chooseColor             : true,\n            chooseFile              : true,\n            chooseFolder            : true,\n            closeWidget             : true,\n            COM                     : true,\n            convertPathToHFS        : true,\n            convertPathToPlatform   : true,\n            CustomAnimation         : true,\n            escape                  : true,\n            FadeAnimation           : true,\n            filesystem              : true,\n            Flash                   : true,\n            focusWidget             : true,\n            form                    : true,\n            FormField               : true,\n            Frame                   : true,\n            HotKey                  : true,\n            Image                   : true,\n            include                 : true,\n            isApplicationRunning    : true,\n            iTunes                  : true,\n            konfabulatorVersion     : true,\n            log                     : true,\n            md5                     : true,\n            MenuItem                : true,\n            MoveAnimation           : true,\n            openURL                 : true,\n            play                    : true,\n            Point                   : true,\n            popupMenu               : true,\n            preferenceGroups        : true,\n            preferences             : true,\n            print                   : true,\n            prompt                  : true,\n            random                  : true,\n            Rectangle               : true,\n            reloadWidget            : true,\n            ResizeAnimation         : true,\n            resolvePath             : true,\n            resumeUpdates           : true,\n            RotateAnimation         : true,\n            runCommand              : true,\n            runCommandInBg          : true,\n            saveAs                  : true,\n            savePreferences         : true,\n            screen                  : true,\n            ScrollBar               : true,\n            showWidgetPreferences   : true,\n            sleep                   : true,\n            speak                   : true,\n            Style                   : true,\n            suppressUpdates         : true,\n            system                  : true,\n            tellWidget              : true,\n            Text                    : true,\n            TextArea                : true,\n            Timer                   : true,\n            unescape                : true,\n            updateNow               : true,\n            URL                     : true,\n            Web                     : true,\n            widget                  : true,\n            Window                  : true,\n            XMLDOM                  : true,\n            XMLHttpRequest          : true,\n            yahooCheckLogin         : true,\n            yahooLogin              : true,\n            yahooLogout             : true\n        },\n\n        windows = {\n            ActiveXObject: false,\n            CScript      : false,\n            Debug        : false,\n            Enumerator   : false,\n            System       : false,\n            VBArray      : false,\n            WScript      : false\n        },\n\n//  xmode is used to adapt to the exceptions in html parsing.\n//  It can have these states:\n//      false   .js script file\n//      html\n//      outer\n//      script\n//      style\n//      scriptstring\n//      styleproperty\n\n        xmode,\n        xquote,\n\n// Regular expressions. Some of these are stupidly long.\n\n// unsafe comment or string\n        ax = /@cc|<\\/?|script|\\]\\s*\\]|<\\s*!|&lt/i,\n// unsafe characters that are silently deleted by one or more browsers\n        cx = /[\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/,\n// token\n        tx = /^\\s*([(){}\\[.,:;'\"~\\?\\]#@]|==?=?|\\/(\\*(jshint|members?|global)?|=|\\/)?|\\*[\\/=]?|\\+(?:=|\\++)?|-(?:=|-+)?|%=?|&[&=]?|\\|[|=]?|>>?>?=?|<([\\/=!]|\\!(\\[|--)?|<=?)?|\\^=?|\\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\\.[0-9]*)?([eE][+\\-]?[0-9]+)?)/,\n// html token\n        hx = /^\\s*(['\"=>\\/&#]|<(?:\\/|\\!(?:--)?)?|[a-zA-Z][a-zA-Z0-9_\\-:]*|[0-9]+|--)/,\n// characters in strings that need escapement\n        nx = /[\\u0000-\\u001f&<\"\\/\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/,\n        nxg = /[\\u0000-\\u001f&<\"\\/\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\n// outer html token\n        ox = /[>&]|<[\\/!]?|--/,\n// star slash\n        lx = /\\*\\/|\\/\\*/,\n// identifier\n        ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/,\n// javascript url\n        jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\\s*:/i,\n// url badness\n        ux = /&|\\+|\\u00AD|\\.\\.|\\/\\*|%[^;]|base64|url|expression|data|mailto/i,\n// style\n        sx = /^\\s*([{:#%.=,>+\\[\\]@()\"';]|\\*=?|\\$=|\\|=|\\^=|~=|[a-zA-Z_][a-zA-Z0-9_\\-]*|[0-9]+|<\\/|\\/\\*)/,\n        ssx = /^\\s*([@#!\"'};:\\-%.=,+\\[\\]()*_]|[a-zA-Z][a-zA-Z0-9._\\-]*|\\/\\*?|\\d+(?:\\.\\d+)?|<\\/)/,\n// attributes characters\n        qx = /[^a-zA-Z0-9+\\-_\\/ ]/,\n// query characters for ids\n        dx = /[\\[\\]\\/\\\\\"'*<>.&:(){}+=#]/,\n\n        rx = {\n            outer: hx,\n            html: hx,\n            style: sx,\n            styleproperty: ssx\n        };\n\n\n    function F() {}     // Used by Object.create\n\n    function is_own(object, name) {\n\n// The object.hasOwnProperty method fails when the property under consideration\n// is named 'hasOwnProperty'. So we have to use this more convoluted form.\n\n        return Object.prototype.hasOwnProperty.call(object, name);\n    }\n\n// Provide critical ES5 functions to ES3.\n\n    if (typeof Array.isArray !== 'function') {\n        Array.isArray = function (o) {\n            return Object.prototype.toString.apply(o) === '[object Array]';\n        };\n    }\n\n    if (typeof Object.create !== 'function') {\n        Object.create = function (o) {\n            F.prototype = o;\n            return new F();\n        };\n    }\n\n    if (typeof Object.keys !== 'function') {\n        Object.keys = function (o) {\n            var a = [], k;\n            for (k in o) {\n                if (is_own(o, k)) {\n                    a.push(k);\n                }\n            }\n            return a;\n        };\n    }\n\n// Non standard methods\n\n    if (typeof String.prototype.entityify !== 'function') {\n        String.prototype.entityify = function () {\n            return this\n                .replace(/&/g, '&amp;')\n                .replace(/</g, '&lt;')\n                .replace(/>/g, '&gt;');\n        };\n    }\n\n    if (typeof String.prototype.isAlpha !== 'function') {\n        String.prototype.isAlpha = function () {\n            return (this >= 'a' && this <= 'z\\uffff') ||\n                (this >= 'A' && this <= 'Z\\uffff');\n        };\n    }\n\n    if (typeof String.prototype.isDigit !== 'function') {\n        String.prototype.isDigit = function () {\n            return (this >= '0' && this <= '9');\n        };\n    }\n\n    if (typeof String.prototype.supplant !== 'function') {\n        String.prototype.supplant = function (o) {\n            return this.replace(/\\{([^{}]*)\\}/g, function (a, b) {\n                var r = o[b];\n                return typeof r === 'string' || typeof r === 'number' ? r : a;\n            });\n        };\n    }\n\n    if (typeof String.prototype.name !== 'function') {\n        String.prototype.name = function () {\n\n// If the string looks like an identifier, then we can return it as is.\n// If the string contains no control characters, no quote characters, and no\n// backslash characters, then we can simply slap some quotes around it.\n// Otherwise we must also replace the offending characters with safe\n// sequences.\n\n            if (ix.test(this)) {\n                return this;\n            }\n            if (nx.test(this)) {\n                return '\"' + this.replace(nxg, function (a) {\n                    var c = escapes[a];\n                    if (c) {\n                        return c;\n                    }\n                    return '\\\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4);\n                }) + '\"';\n            }\n            return '\"' + this + '\"';\n        };\n    }\n\n\n    function combine(t, o) {\n        var n;\n        for (n in o) {\n            if (is_own(o, n)) {\n                t[n] = o[n];\n            }\n        }\n    }\n\n    function assume() {\n        if (!option.safe) {\n            if (option.rhino) {\n                combine(predefined, rhino);\n            }\n            if (option.node) {\n                combine(predefined, node);\n            }\n            if (option.devel) {\n                combine(predefined, devel);\n            }\n            if (option.browser) {\n                combine(predefined, browser);\n            }\n            if (option.windows) {\n                combine(predefined, windows);\n            }\n            if (option.widget) {\n                combine(predefined, widget);\n            }\n        }\n    }\n\n\n// Produce an error warning.\n\n    function quit(m, l, ch) {\n        throw {\n            name: 'JSHintError',\n            line: l,\n            character: ch,\n            message: m + \" (\" + Math.floor((l / lines.length) * 100) +\n                    \"% scanned).\"\n        };\n    }\n\n    function warning(m, t, a, b, c, d) {\n        var ch, l, w;\n        t = t || nexttoken;\n        if (t.id === '(end)') {  // `~\n            t = token;\n        }\n        l = t.line || 0;\n        ch = t.from || 0;\n        w = {\n            id: '(error)',\n            raw: m,\n            evidence: lines[l - 1] || '',\n            line: l,\n            character: ch,\n            a: a,\n            b: b,\n            c: c,\n            d: d\n        };\n        w.reason = m.supplant(w);\n        JSHINT.errors.push(w);\n        if (option.passfail) {\n            quit('Stopping. ', l, ch);\n        }\n        warnings += 1;\n        if (warnings >= option.maxerr) {\n            quit(\"Too many errors.\", l, ch);\n        }\n        return w;\n    }\n\n    function warningAt(m, l, ch, a, b, c, d) {\n        return warning(m, {\n            line: l,\n            from: ch\n        }, a, b, c, d);\n    }\n\n    function error(m, t, a, b, c, d) {\n        var w = warning(m, t, a, b, c, d);\n        quit(\"Stopping, unable to continue.\", w.line, w.character);\n    }\n\n    function errorAt(m, l, ch, a, b, c, d) {\n        return error(m, {\n            line: l,\n            from: ch\n        }, a, b, c, d);\n    }\n\n\n\n// lexical analysis and token construction\n\n    var lex = (function lex() {\n        var character, from, line, s;\n\n// Private lex methods\n\n        function nextLine() {\n            var at;\n            if (line >= lines.length) {\n                return false;\n            }\n            character = 1;\n            s = lines[line];\n            line += 1;\n            at = s.search(/ \\t/);\n            if (at >= 0) {\n                warningAt(\"Mixed spaces and tabs.\", line, at + 1);\n            }\n            s = s.replace(/\\t/g, tab);\n            at = s.search(cx);\n            if (at >= 0) {\n                warningAt(\"Unsafe character.\", line, at);\n            }\n            if (option.maxlen && option.maxlen < s.length) {\n                warningAt(\"Line too long.\", line, s.length);\n            }\n            return true;\n        }\n\n// Produce a token object.  The token inherits from a syntax symbol.\n\n        function it(type, value) {\n            var i, t;\n            if (type === '(color)' || type === '(range)') {\n                t = {type: type};\n            } else if (type === '(punctuator)' ||\n                    (type === '(identifier)' && is_own(syntax, value))) {\n                t = syntax[value] || syntax['(error)'];\n            } else {\n                t = syntax[type];\n            }\n            t = Object.create(t);\n            if (type === '(string)' || type === '(range)') {\n                if (jx.test(value)) {\n                    warningAt(\"Script URL.\", line, from);\n                }\n            }\n            if (type === '(identifier)') {\n                t.identifier = true;\n                if (value === '__iterator__' || value === '__proto__') {\n                    errorAt(\"Reserved name '{a}'.\",\n                        line, from, value);\n                } else if (option.nomen &&\n                        (value.charAt(0) === '_' ||\n                         value.charAt(value.length - 1) === '_')) {\n                    warningAt(\"Unexpected {a} in '{b}'.\", line, from,\n                        \"dangling '_'\", value);\n                }\n            }\n            t.value = value;\n            t.line = line;\n            t.character = character;\n            t.from = from;\n            i = t.id;\n            if (i !== '(endline)') {\n                prereg = i &&\n                    (('(,=:[!&|?{};'.indexOf(i.charAt(i.length - 1)) >= 0) ||\n                    i === 'return');\n            }\n            return t;\n        }\n\n// Public lex methods\n\n        return {\n            init: function (source) {\n                if (typeof source === 'string') {\n                    lines = source\n                        .replace(/\\r\\n/g, '\\n')\n                        .replace(/\\r/g, '\\n')\n                        .split('\\n');\n                } else {\n                    lines = source;\n                }\n                line = 0;\n                nextLine();\n                from = 1;\n            },\n\n            range: function (begin, end) {\n                var c, value = '';\n                from = character;\n                if (s.charAt(0) !== begin) {\n                    errorAt(\"Expected '{a}' and instead saw '{b}'.\",\n                            line, character, begin, s.charAt(0));\n                }\n                for (;;) {\n                    s = s.slice(1);\n                    character += 1;\n                    c = s.charAt(0);\n                    switch (c) {\n                    case '':\n                        errorAt(\"Missing '{a}'.\", line, character, c);\n                        break;\n                    case end:\n                        s = s.slice(1);\n                        character += 1;\n                        return it('(range)', value);\n                    case xquote:\n                    case '\\\\':\n                        warningAt(\"Unexpected '{a}'.\", line, character, c);\n                    }\n                    value += c;\n                }\n\n            },\n\n// token -- this is called by advance to get the next token.\n\n            token: function () {\n                var b, c, captures, d, depth, high, i, l, low, q, t;\n\n                function match(x) {\n                    var r = x.exec(s), r1;\n                    if (r) {\n                        l = r[0].length;\n                        r1 = r[1];\n                        c = r1.charAt(0);\n                        s = s.substr(l);\n                        from = character + l - r1.length;\n                        character += l;\n                        return r1;\n                    }\n                }\n\n                function string(x) {\n                    var c, j, r = '';\n\n                    if (jsonmode && x !== '\"') {\n                        warningAt(\"Strings must use doublequote.\",\n                                line, character);\n                    }\n\n                    if (xquote === x || (xmode === 'scriptstring' && !xquote)) {\n                        return it('(punctuator)', x);\n                    }\n\n                    function esc(n) {\n                        var i = parseInt(s.substr(j + 1, n), 16);\n                        j += n;\n                        if (i >= 32 && i <= 126 &&\n                                i !== 34 && i !== 92 && i !== 39) {\n                            warningAt(\"Unnecessary escapement.\", line, character);\n                        }\n                        character += n;\n                        c = String.fromCharCode(i);\n                    }\n                    j = 0;\n                    for (;;) {\n                        while (j >= s.length) {\n                            j = 0;\n                            if (xmode !== 'html' || !nextLine()) {\n                                errorAt(\"Unclosed string.\", line, from);\n                            }\n                        }\n                        c = s.charAt(j);\n                        if (c === x) {\n                            character += 1;\n                            s = s.substr(j + 1);\n                            return it('(string)', r, x);\n                        }\n                        if (c < ' ') {\n                            if (c === '\\n' || c === '\\r') {\n                                break;\n                            }\n                            warningAt(\"Control character in string: {a}.\",\n                                    line, character + j, s.slice(0, j));\n                        } else if (c === xquote) {\n                            warningAt(\"Bad HTML string\", line, character + j);\n                        } else if (c === '<') {\n                            if (option.safe && xmode === 'html') {\n                                warningAt(\"ADsafe string violation.\",\n                                        line, character + j);\n                            } else if (s.charAt(j + 1) === '/' && (xmode || option.safe)) {\n                                warningAt(\"Expected '<\\\\/' and instead saw '</'.\", line, character);\n                            } else if (s.charAt(j + 1) === '!' && (xmode || option.safe)) {\n                                warningAt(\"Unexpected '<!' in a string.\", line, character);\n                            }\n                        } else if (c === '\\\\') {\n                            if (xmode === 'html') {\n                                if (option.safe) {\n                                    warningAt(\"ADsafe string violation.\",\n                                            line, character + j);\n                                }\n                            } else if (xmode === 'styleproperty') {\n                                j += 1;\n                                character += 1;\n                                c = s.charAt(j);\n                                if (c !== x) {\n                                    warningAt(\"Escapement in style string.\",\n                                            line, character + j);\n                                }\n                            } else {\n                                j += 1;\n                                character += 1;\n                                c = s.charAt(j);\n                                switch (c) {\n                                case xquote:\n                                    warningAt(\"Bad HTML string\", line,\n                                        character + j);\n                                    break;\n                                case '\\\\':\n                                case '\"':\n                                case '/':\n                                    break;\n                                case '\\'':\n                                    if (jsonmode) {\n                                        warningAt(\"Avoid \\\\'.\", line, character);\n                                    }\n                                    break;\n                                case 'b':\n                                    c = '\\b';\n                                    break;\n                                case 'f':\n                                    c = '\\f';\n                                    break;\n                                case 'n':\n                                    c = '\\n';\n                                    break;\n                                case 'r':\n                                    c = '\\r';\n                                    break;\n                                case 't':\n                                    c = '\\t';\n                                    break;\n                                case 'u':\n                                    esc(4);\n                                    break;\n                                case 'v':\n                                    if (jsonmode) {\n                                        warningAt(\"Avoid \\\\v.\", line, character);\n                                    }\n                                    c = '\\v';\n                                    break;\n                                case 'x':\n                                    if (jsonmode) {\n                                        warningAt(\"Avoid \\\\x-.\", line, character);\n                                    }\n                                    esc(2);\n                                    break;\n                                default:\n                                    warningAt(\"Bad escapement.\", line, character);\n                                }\n                            }\n                        }\n                        r += c;\n                        character += 1;\n                        j += 1;\n                    }\n                }\n\n                for (;;) {\n                    if (!s) {\n                        return it(nextLine() ? '(endline)' : '(end)', '');\n                    }\n                    while (xmode === 'outer') {\n                        i = s.search(ox);\n                        if (i === 0) {\n                            break;\n                        } else if (i > 0) {\n                            character += 1;\n                            s = s.slice(i);\n                            break;\n                        } else {\n                            if (!nextLine()) {\n                                return it('(end)', '');\n                            }\n                        }\n                    }\n                    t = match(rx[xmode] || tx);\n                    if (!t) {\n                        t = '';\n                        c = '';\n                        while (s && s < '!') {\n                            s = s.substr(1);\n                        }\n                        if (s) {\n                            if (xmode === 'html') {\n                                return it('(error)', s.charAt(0));\n                            } else {\n                                errorAt(\"Unexpected '{a}'.\",\n                                        line, character, s.substr(0, 1));\n                            }\n                        }\n                    } else {\n\n    //      identifier\n\n                        if (c.isAlpha() || c === '_' || c === '$') {\n                            return it('(identifier)', t);\n                        }\n\n    //      number\n\n                        if (c.isDigit()) {\n                            if (xmode !== 'style' && !isFinite(Number(t))) {\n                                warningAt(\"Bad number '{a}'.\",\n                                    line, character, t);\n                            }\n                            if (xmode !== 'style' &&\n                                     xmode !== 'styleproperty' &&\n                                     s.substr(0, 1).isAlpha()) {\n                                warningAt(\"Missing space after '{a}'.\",\n                                        line, character, t);\n                            }\n                            if (c === '0') {\n                                d = t.substr(1, 1);\n                                if (d.isDigit()) {\n                                    if (token.id !== '.' && xmode !== 'styleproperty') {\n                                        warningAt(\"Don't use extra leading zeros '{a}'.\",\n                                            line, character, t);\n                                    }\n                                } else if (jsonmode && (d === 'x' || d === 'X')) {\n                                    warningAt(\"Avoid 0x-. '{a}'.\",\n                                            line, character, t);\n                                }\n                            }\n                            if (t.substr(t.length - 1) === '.') {\n                                warningAt(\n\"A trailing decimal point can be confused with a dot '{a}'.\", line, character, t);\n                            }\n                            return it('(number)', t);\n                        }\n                        switch (t) {\n\n    //      string\n\n                        case '\"':\n                        case \"'\":\n                            return string(t);\n\n    //      // comment\n\n                        case '//':\n                            if (src || (xmode && xmode !== 'script')) {\n                                warningAt(\"Unexpected comment.\", line, character);\n                            } else if (xmode === 'script' && /<\\s*\\//i.test(s)) {\n                                warningAt(\"Unexpected <\\/ in comment.\", line, character);\n                            } else if ((option.safe || xmode === 'script') && ax.test(s)) {\n                                warningAt(\"Dangerous comment.\", line, character);\n                            }\n                            s = '';\n                            token.comment = true;\n                            break;\n\n    //      /* comment\n\n                        case '/*':\n                            if (src || (xmode && xmode !== 'script' && xmode !== 'style' && xmode !== 'styleproperty')) {\n                                warningAt(\"Unexpected comment.\", line, character);\n                            }\n                            if (option.safe && ax.test(s)) {\n                                warningAt(\"ADsafe comment violation.\", line, character);\n                            }\n                            for (;;) {\n                                i = s.search(lx);\n                                if (i >= 0) {\n                                    break;\n                                }\n                                if (!nextLine()) {\n                                    errorAt(\"Unclosed comment.\", line, character);\n                                } else {\n                                    if (option.safe && ax.test(s)) {\n                                        warningAt(\"ADsafe comment violation.\",\n                                                line, character);\n                                    }\n                                }\n                            }\n                            character += i + 2;\n                            if (s.substr(i, 1) === '/') {\n                                errorAt(\"Nested comment.\", line, character);\n                            }\n                            s = s.substr(i + 2);\n                            token.comment = true;\n                            break;\n\n    //      /*members /*jshint /*global\n\n                        case '/*members':\n                        case '/*member':\n                        case '/*jshint':\n                        case '/*global':\n                        case '*/':\n                            return {\n                                value: t,\n                                type: 'special',\n                                line: line,\n                                character: character,\n                                from: from\n                            };\n\n                        case '':\n                            break;\n    //      /\n                        case '/':\n                            if (token.id === '/=') {\n                                errorAt(\n\"A regular expression literal can be confused with '/='.\", line, from);\n                            }\n                            if (prereg) {\n                                depth = 0;\n                                captures = 0;\n                                l = 0;\n                                for (;;) {\n                                    b = true;\n                                    c = s.charAt(l);\n                                    l += 1;\n                                    switch (c) {\n                                    case '':\n                                        errorAt(\"Unclosed regular expression.\",\n                                                line, from);\n                                        return;\n                                    case '/':\n                                        if (depth > 0) {\n                                            warningAt(\"Unescaped '{a}'.\",\n                                                    line, from + l, '/');\n                                        }\n                                        c = s.substr(0, l - 1);\n                                        q = {\n                                            g: true,\n                                            i: true,\n                                            m: true\n                                        };\n                                        while (q[s.charAt(l)] === true) {\n                                            q[s.charAt(l)] = false;\n                                            l += 1;\n                                        }\n                                        character += l;\n                                        s = s.substr(l);\n                                        q = s.charAt(0);\n                                        if (q === '/' || q === '*') {\n                                            errorAt(\"Confusing regular expression.\",\n                                                    line, from);\n                                        }\n                                        return it('(regexp)', c);\n                                    case '\\\\':\n                                        c = s.charAt(l);\n                                        if (c < ' ') {\n                                            warningAt(\n\"Unexpected control character in regular expression.\", line, from + l);\n                                        } else if (c === '<') {\n                                            warningAt(\n\"Unexpected escaped character '{a}' in regular expression.\", line, from + l, c);\n                                        }\n                                        l += 1;\n                                        break;\n                                    case '(':\n                                        depth += 1;\n                                        b = false;\n                                        if (s.charAt(l) === '?') {\n                                            l += 1;\n                                            switch (s.charAt(l)) {\n                                            case ':':\n                                            case '=':\n                                            case '!':\n                                                l += 1;\n                                                break;\n                                            default:\n                                                warningAt(\n\"Expected '{a}' and instead saw '{b}'.\", line, from + l, ':', s.charAt(l));\n                                            }\n                                        } else {\n                                            captures += 1;\n                                        }\n                                        break;\n                                    case '|':\n                                        b = false;\n                                        break;\n                                    case ')':\n                                        if (depth === 0) {\n                                            warningAt(\"Unescaped '{a}'.\",\n                                                    line, from + l, ')');\n                                        } else {\n                                            depth -= 1;\n                                        }\n                                        break;\n                                    case ' ':\n                                        q = 1;\n                                        while (s.charAt(l) === ' ') {\n                                            l += 1;\n                                            q += 1;\n                                        }\n                                        if (q > 1) {\n                                            warningAt(\n\"Spaces are hard to count. Use {{a}}.\", line, from + l, q);\n                                        }\n                                        break;\n                                    case '[':\n                                        c = s.charAt(l);\n                                        if (c === '^') {\n                                            l += 1;\n                                            if (option.regexp) {\n                                                warningAt(\"Insecure '{a}'.\",\n                                                        line, from + l, c);\n                                            } else if (s.charAt(l) === ']') {\n                                                errorAt(\"Unescaped '{a}'.\",\n                                                    line, from + l, '^');\n                                            }\n                                        }\n                                        q = false;\n                                        if (c === ']') {\n                                            warningAt(\"Empty class.\", line,\n                                                    from + l - 1);\n                                            q = true;\n                                        }\nklass:                                  do {\n                                            c = s.charAt(l);\n                                            l += 1;\n                                            switch (c) {\n                                            case '[':\n                                            case '^':\n                                                warningAt(\"Unescaped '{a}'.\",\n                                                        line, from + l, c);\n                                                q = true;\n                                                break;\n                                            case '-':\n                                                if (q) {\n                                                    q = false;\n                                                } else {\n                                                    warningAt(\"Unescaped '{a}'.\",\n                                                            line, from + l, '-');\n                                                    q = true;\n                                                }\n                                                break;\n                                            case ']':\n                                                if (!q) {\n                                                    warningAt(\"Unescaped '{a}'.\",\n                                                            line, from + l - 1, '-');\n                                                }\n                                                break klass;\n                                            case '\\\\':\n                                                c = s.charAt(l);\n                                                if (c < ' ') {\n                                                    warningAt(\n\"Unexpected control character in regular expression.\", line, from + l);\n                                                } else if (c === '<') {\n                                                    warningAt(\n\"Unexpected escaped character '{a}' in regular expression.\", line, from + l, c);\n                                                }\n                                                l += 1;\n                                                q = true;\n                                                break;\n                                            case '/':\n                                                warningAt(\"Unescaped '{a}'.\",\n                                                        line, from + l - 1, '/');\n                                                q = true;\n                                                break;\n                                            case '<':\n                                                if (xmode === 'script') {\n                                                    c = s.charAt(l);\n                                                    if (c === '!' || c === '/') {\n                                                        warningAt(\n\"HTML confusion in regular expression '<{a}'.\", line, from + l, c);\n                                                    }\n                                                }\n                                                q = true;\n                                                break;\n                                            default:\n                                                q = true;\n                                            }\n                                        } while (c);\n                                        break;\n                                    case '.':\n                                        if (option.regexp) {\n                                            warningAt(\"Insecure '{a}'.\", line,\n                                                    from + l, c);\n                                        }\n                                        break;\n                                    case ']':\n                                    case '?':\n                                    case '{':\n                                    case '}':\n                                    case '+':\n                                    case '*':\n                                        warningAt(\"Unescaped '{a}'.\", line,\n                                                from + l, c);\n                                        break;\n                                    case '<':\n                                        if (xmode === 'script') {\n                                            c = s.charAt(l);\n                                            if (c === '!' || c === '/') {\n                                                warningAt(\n\"HTML confusion in regular expression '<{a}'.\", line, from + l, c);\n                                            }\n                                        }\n                                    }\n                                    if (b) {\n                                        switch (s.charAt(l)) {\n                                        case '?':\n                                        case '+':\n                                        case '*':\n                                            l += 1;\n                                            if (s.charAt(l) === '?') {\n                                                l += 1;\n                                            }\n                                            break;\n                                        case '{':\n                                            l += 1;\n                                            c = s.charAt(l);\n                                            if (c < '0' || c > '9') {\n                                                warningAt(\n\"Expected a number and instead saw '{a}'.\", line, from + l, c);\n                                            }\n                                            l += 1;\n                                            low = +c;\n                                            for (;;) {\n                                                c = s.charAt(l);\n                                                if (c < '0' || c > '9') {\n                                                    break;\n                                                }\n                                                l += 1;\n                                                low = +c + (low * 10);\n                                            }\n                                            high = low;\n                                            if (c === ',') {\n                                                l += 1;\n                                                high = Infinity;\n                                                c = s.charAt(l);\n                                                if (c >= '0' && c <= '9') {\n                                                    l += 1;\n                                                    high = +c;\n                                                    for (;;) {\n                                                        c = s.charAt(l);\n                                                        if (c < '0' || c > '9') {\n                                                            break;\n                                                        }\n                                                        l += 1;\n                                                        high = +c + (high * 10);\n                                                    }\n                                                }\n                                            }\n                                            if (s.charAt(l) !== '}') {\n                                                warningAt(\n\"Expected '{a}' and instead saw '{b}'.\", line, from + l, '}', c);\n                                            } else {\n                                                l += 1;\n                                            }\n                                            if (s.charAt(l) === '?') {\n                                                l += 1;\n                                            }\n                                            if (low > high) {\n                                                warningAt(\n\"'{a}' should not be greater than '{b}'.\", line, from + l, low, high);\n                                            }\n                                        }\n                                    }\n                                }\n                                c = s.substr(0, l - 1);\n                                character += l;\n                                s = s.substr(l);\n                                return it('(regexp)', c);\n                            }\n                            return it('(punctuator)', t);\n\n    //      punctuator\n\n                        case '<!--':\n                            l = line;\n                            c = character;\n                            for (;;) {\n                                i = s.indexOf('--');\n                                if (i >= 0) {\n                                    break;\n                                }\n                                i = s.indexOf('<!');\n                                if (i >= 0) {\n                                    errorAt(\"Nested HTML comment.\",\n                                        line, character + i);\n                                }\n                                if (!nextLine()) {\n                                    errorAt(\"Unclosed HTML comment.\", l, c);\n                                }\n                            }\n                            l = s.indexOf('<!');\n                            if (l >= 0 && l < i) {\n                                errorAt(\"Nested HTML comment.\",\n                                    line, character + l);\n                            }\n                            character += i;\n                            if (s.charAt(i + 2) !== '>') {\n                                errorAt(\"Expected -->.\", line, character);\n                            }\n                            character += 3;\n                            s = s.slice(i + 3);\n                            break;\n                        case '#':\n                            if (xmode === 'html' || xmode === 'styleproperty') {\n                                for (;;) {\n                                    c = s.charAt(0);\n                                    if ((c < '0' || c > '9') &&\n                                            (c < 'a' || c > 'f') &&\n                                            (c < 'A' || c > 'F')) {\n                                        break;\n                                    }\n                                    character += 1;\n                                    s = s.substr(1);\n                                    t += c;\n                                }\n                                if (t.length !== 4 && t.length !== 7) {\n                                    warningAt(\"Bad hex color '{a}'.\", line,\n                                        from + l, t);\n                                }\n                                return it('(color)', t);\n                            }\n                            return it('(punctuator)', t);\n                        default:\n                            if (xmode === 'outer' && c === '&') {\n                                character += 1;\n                                s = s.substr(1);\n                                for (;;) {\n                                    c = s.charAt(0);\n                                    character += 1;\n                                    s = s.substr(1);\n                                    if (c === ';') {\n                                        break;\n                                    }\n                                    if (!((c >= '0' && c <= '9') ||\n                                            (c >= 'a' && c <= 'z') ||\n                                            c === '#')) {\n                                        errorAt(\"Bad entity\", line, from + l,\n                                        character);\n                                    }\n                                }\n                                break;\n                            }\n                            return it('(punctuator)', t);\n                        }\n                    }\n                }\n            }\n        };\n    }());\n\n\n    function addlabel(t, type) {\n\n        if (option.safe && funct['(global)'] &&\n                typeof predefined[t] !== 'boolean') {\n            warning('ADsafe global: ' + t + '.', token);\n        } else if (t === 'hasOwnProperty') {\n            warning(\"'hasOwnProperty' is a really bad name.\");\n        }\n\n// Define t in the current function in the current scope.\n\n        if (is_own(funct, t) && !funct['(global)']) {\n            warning(funct[t] === true ?\n                \"'{a}' was used before it was defined.\" :\n                \"'{a}' is already defined.\",\n                nexttoken, t);\n        }\n        funct[t] = type;\n        if (funct['(global)']) {\n            global[t] = funct;\n            if (is_own(implied, t)) {\n                warning(\"'{a}' was used before it was defined.\", nexttoken, t);\n                delete implied[t];\n            }\n        } else {\n            scope[t] = funct;\n        }\n    }\n\n\n    function doOption() {\n        var b, obj, filter, o = nexttoken.value, t, v;\n        switch (o) {\n        case '*/':\n            error(\"Unbegun comment.\");\n            break;\n        case '/*members':\n        case '/*member':\n            o = '/*members';\n            if (!membersOnly) {\n                membersOnly = {};\n            }\n            obj = membersOnly;\n            break;\n        case '/*jshint':\n            if (option.safe) {\n                warning(\"ADsafe restriction.\");\n            }\n            obj = option;\n            filter = boolOptions;\n            break;\n        case '/*global':\n            if (option.safe) {\n                warning(\"ADsafe restriction.\");\n            }\n            obj = predefined;\n            break;\n        default:\n            error(\"What?\");\n        }\n        t = lex.token();\nloop:   for (;;) {\n            for (;;) {\n                if (t.type === 'special' && t.value === '*/') {\n                    break loop;\n                }\n                if (t.id !== '(endline)' && t.id !== ',') {\n                    break;\n                }\n                t = lex.token();\n            }\n            if (t.type !== '(string)' && t.type !== '(identifier)' &&\n                    o !== '/*members') {\n                error(\"Bad option.\", t);\n            }\n            v = lex.token();\n            if (v.id === ':') {\n                v = lex.token();\n                if (obj === membersOnly) {\n                    error(\"Expected '{a}' and instead saw '{b}'.\",\n                            t, '*/', ':');\n                }\n                if (t.value === 'indent' && o === '/*jshint') {\n                    b = +v.value;\n                    if (typeof b !== 'number' || !isFinite(b) || b <= 0 ||\n                            Math.floor(b) !== b) {\n                        error(\"Expected a small integer and instead saw '{a}'.\",\n                                v, v.value);\n                    }\n                    obj.white = true;\n                    obj.indent = b;\n                } else if (t.value === 'maxerr' && o === '/*jshint') {\n                    b = +v.value;\n                    if (typeof b !== 'number' || !isFinite(b) || b <= 0 ||\n                            Math.floor(b) !== b) {\n                        error(\"Expected a small integer and instead saw '{a}'.\",\n                                v, v.value);\n                    }\n                    obj.maxerr = b;\n                } else if (t.value === 'maxlen' && o === '/*jshint') {\n                    b = +v.value;\n                    if (typeof b !== 'number' || !isFinite(b) || b <= 0 ||\n                            Math.floor(b) !== b) {\n                        error(\"Expected a small integer and instead saw '{a}'.\",\n                                v, v.value);\n                    }\n                    obj.maxlen = b;\n                } else if (v.value === 'true') {\n                    obj[t.value] = true;\n                } else if (v.value === 'false') {\n                    obj[t.value] = false;\n                } else {\n                    error(\"Bad option value.\", v);\n                }\n                t = lex.token();\n            } else {\n                if (o === '/*jshint') {\n                    error(\"Missing option value.\", t);\n                }\n                obj[t.value] = false;\n                t = v;\n            }\n        }\n        if (filter) {\n            assume();\n        }\n    }\n\n\n// We need a peek function. If it has an argument, it peeks that much farther\n// ahead. It is used to distinguish\n//     for ( var i in ...\n// from\n//     for ( var i = ...\n\n    function peek(p) {\n        var i = p || 0, j = 0, t;\n\n        while (j <= i) {\n            t = lookahead[j];\n            if (!t) {\n                t = lookahead[j] = lex.token();\n            }\n            j += 1;\n        }\n        return t;\n    }\n\n\n\n// Produce the next token. It looks for programming errors.\n\n    function advance(id, t) {\n        switch (token.id) {\n        case '(number)':\n            if (nexttoken.id === '.') {\n                warning(\n\"A dot following a number can be confused with a decimal point.\", token);\n            }\n            break;\n        case '-':\n            if (nexttoken.id === '-' || nexttoken.id === '--') {\n                warning(\"Confusing minusses.\");\n            }\n            break;\n        case '+':\n            if (nexttoken.id === '+' || nexttoken.id === '++') {\n                warning(\"Confusing plusses.\");\n            }\n            break;\n        }\n        if (token.type === '(string)' || token.identifier) {\n            anonname = token.value;\n        }\n\n        if (id && nexttoken.id !== id) {\n            if (t) {\n                if (nexttoken.id === '(end)') {\n                    warning(\"Unmatched '{a}'.\", t, t.id);\n                } else {\n                    warning(\n\"Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.\",\n                            nexttoken, id, t.id, t.line, nexttoken.value);\n                }\n            } else if (nexttoken.type !== '(identifier)' ||\n                            nexttoken.value !== id) {\n                warning(\"Expected '{a}' and instead saw '{b}'.\",\n                        nexttoken, id, nexttoken.value);\n            }\n        }\n        prevtoken = token;\n        token = nexttoken;\n        for (;;) {\n            nexttoken = lookahead.shift() || lex.token();\n            if (nexttoken.id === '(end)' || nexttoken.id === '(error)') {\n                return;\n            }\n            if (nexttoken.type === 'special') {\n                doOption();\n            } else {\n                if (nexttoken.id !== '(endline)') {\n                    break;\n                }\n            }\n        }\n    }\n\n\n// This is the heart of JSHINT, the Pratt parser. In addition to parsing, it\n// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is\n// like .nud except that it is only used on the first token of a statement.\n// Having .fud makes it much easier to define statement-oriented languages like\n// JavaScript. I retained Pratt's nomenclature.\n\n// .nud     Null denotation\n// .fud     First null denotation\n// .led     Left denotation\n//  lbp     Left binding power\n//  rbp     Right binding power\n\n// They are elements of the parsing method called Top Down Operator Precedence.\n\n    function expression(rbp, initial) {\n        var left;\n        if (nexttoken.id === '(end)') {\n            error(\"Unexpected early end of program.\", token);\n        }\n        advance();\n        if (option.safe && typeof predefined[token.value] === 'boolean' &&\n                (nexttoken.id !== '(' && nexttoken.id !== '.')) {\n            warning('ADsafe violation.', token);\n        }\n        if (initial) {\n            anonname = 'anonymous';\n            funct['(verb)'] = token.value;\n        }\n        if (initial === true && token.fud) {\n            left = token.fud();\n        } else {\n            if (token.nud) {\n                left = token.nud();\n            } else {\n                if (nexttoken.type === '(number)' && token.id === '.') {\n                    warning(\n\"A leading decimal point can be confused with a dot: '.{a}'.\",\n                            token, nexttoken.value);\n                    advance();\n                    return token;\n                } else {\n                    error(\"Expected an identifier and instead saw '{a}'.\",\n                            token, token.id);\n                }\n            }\n            while (rbp < nexttoken.lbp) {\n                advance();\n                if (token.led) {\n                    left = token.led(left);\n                } else {\n                    error(\"Expected an operator and instead saw '{a}'.\",\n                        token, token.id);\n                }\n            }\n        }\n        return left;\n    }\n\n\n// Functions for conformance of style.\n\n    function adjacent(left, right) {\n        left = left || token;\n        right = right || nexttoken;\n        if (option.white || xmode === 'styleproperty' || xmode === 'style') {\n            if (left.character !== right.from && left.line === right.line) {\n                warning(\"Unexpected space after '{a}'.\", right, left.value);\n            }\n        }\n    }\n\n    function nobreak(left, right) {\n        left = left || token;\n        right = right || nexttoken;\n        if (option.white && (left.character !== right.from || left.line !== right.line)) {\n            warning(\"Unexpected space before '{a}'.\", right, right.value);\n        }\n    }\n\n    function nospace(left, right) {\n        left = left || token;\n        right = right || nexttoken;\n        if (option.white && !left.comment) {\n            if (left.line === right.line) {\n                adjacent(left, right);\n            }\n        }\n    }\n\n    function nonadjacent(left, right) {\n        if (option.white) {\n            left = left || token;\n            right = right || nexttoken;\n            if (left.line === right.line && left.character === right.from) {\n                warning(\"Missing space after '{a}'.\",\n                        nexttoken, left.value);\n            }\n        }\n    }\n\n    function nobreaknonadjacent(left, right) {\n        left = left || token;\n        right = right || nexttoken;\n        if (!option.laxbreak && left.line !== right.line) {\n            warning(\"Bad line breaking before '{a}'.\", right, right.id);\n        } else if (option.white) {\n            left = left || token;\n            right = right || nexttoken;\n            if (left.character === right.from) {\n                warning(\"Missing space after '{a}'.\",\n                        nexttoken, left.value);\n            }\n        }\n    }\n\n    function indentation(bias) {\n        var i;\n        if (option.white && nexttoken.id !== '(end)') {\n            i = indent + (bias || 0);\n            if (nexttoken.from !== i) {\n                warning(\n\"Expected '{a}' to have an indentation at {b} instead at {c}.\",\n                        nexttoken, nexttoken.value, i, nexttoken.from);\n            }\n        }\n    }\n\n    function nolinebreak(t) {\n        t = t || token;\n        if (t.line !== nexttoken.line) {\n            warning(\"Line breaking error '{a}'.\", t, t.value);\n        }\n    }\n\n\n    function comma() {\n        if (token.line !== nexttoken.line) {\n            if (!option.laxbreak) {\n                warning(\"Bad line breaking before '{a}'.\", token, nexttoken.id);\n            }\n        } else if (token.character !== nexttoken.from && option.white) {\n            warning(\"Unexpected space after '{a}'.\", nexttoken, token.value);\n        }\n        advance(',');\n        nonadjacent(token, nexttoken);\n    }\n\n\n// Functional constructors for making the symbols that will be inherited by\n// tokens.\n\n    function symbol(s, p) {\n        var x = syntax[s];\n        if (!x || typeof x !== 'object') {\n            syntax[s] = x = {\n                id: s,\n                lbp: p,\n                value: s\n            };\n        }\n        return x;\n    }\n\n\n    function delim(s) {\n        return symbol(s, 0);\n    }\n\n\n    function stmt(s, f) {\n        var x = delim(s);\n        x.identifier = x.reserved = true;\n        x.fud = f;\n        return x;\n    }\n\n\n    function blockstmt(s, f) {\n        var x = stmt(s, f);\n        x.block = true;\n        return x;\n    }\n\n\n    function reserveName(x) {\n        var c = x.id.charAt(0);\n        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {\n            x.identifier = x.reserved = true;\n        }\n        return x;\n    }\n\n\n    function prefix(s, f) {\n        var x = symbol(s, 150);\n        reserveName(x);\n        x.nud = (typeof f === 'function') ? f : function () {\n            this.right = expression(150);\n            this.arity = 'unary';\n            if (this.id === '++' || this.id === '--') {\n                if (option.plusplus) {\n                    warning(\"Unexpected use of '{a}'.\", this, this.id);\n                } else if ((!this.right.identifier || this.right.reserved) &&\n                        this.right.id !== '.' && this.right.id !== '[') {\n                    warning(\"Bad operand.\", this);\n                }\n            }\n            return this;\n        };\n        return x;\n    }\n\n\n    function type(s, f) {\n        var x = delim(s);\n        x.type = s;\n        x.nud = f;\n        return x;\n    }\n\n\n    function reserve(s, f) {\n        var x = type(s, f);\n        x.identifier = x.reserved = true;\n        return x;\n    }\n\n\n    function reservevar(s, v) {\n        return reserve(s, function () {\n            if (typeof v === 'function') {\n                v(this);\n            }\n            return this;\n        });\n    }\n\n\n    function infix(s, f, p, w) {\n        var x = symbol(s, p);\n        reserveName(x);\n        x.led = function (left) {\n            if (!w) {\n                nobreaknonadjacent(prevtoken, token);\n                nonadjacent(token, nexttoken);\n            }\n            if (typeof f === 'function') {\n                return f(left, this);\n            } else {\n                this.left = left;\n                this.right = expression(p);\n                return this;\n            }\n        };\n        return x;\n    }\n\n\n    function relation(s, f) {\n        var x = symbol(s, 100);\n        x.led = function (left) {\n            nobreaknonadjacent(prevtoken, token);\n            nonadjacent(token, nexttoken);\n            var right = expression(100);\n            if ((left && left.id === 'NaN') || (right && right.id === 'NaN')) {\n                warning(\"Use the isNaN function to compare with NaN.\", this);\n            } else if (f) {\n                f.apply(this, [left, right]);\n            }\n            if (left.id === '!') {\n                warning(\"Confusing use of '{a}'.\", left, '!');\n            }\n            if (right.id === '!') {\n                warning(\"Confusing use of '{a}'.\", left, '!');\n            }\n            this.left = left;\n            this.right = right;\n            return this;\n        };\n        return x;\n    }\n\n\n    function isPoorRelation(node) {\n        return node &&\n              ((node.type === '(number)' && +node.value === 0) ||\n               (node.type === '(string)' && node.value === '') ||\n                node.type === 'true' ||\n                node.type === 'false' ||\n                node.type === 'undefined' ||\n                node.type === 'null');\n    }\n\n\n    function assignop(s, f) {\n        symbol(s, 20).exps = true;\n        return infix(s, function (left, that) {\n            var l;\n            that.left = left;\n            if (predefined[left.value] === false &&\n                    scope[left.value]['(global)'] === true) {\n                warning(\"Read only.\", left);\n            } else if (left['function']) {\n                warning(\"'{a}' is a function.\", left, left.value);\n            }\n            if (option.safe) {\n                l = left;\n                do {\n                    if (typeof predefined[l.value] === 'boolean') {\n                        warning('ADsafe violation.', l);\n                    }\n                    l = l.left;\n                } while (l);\n            }\n            if (left) {\n                if (left.id === '.' || left.id === '[') {\n                    if (!left.left || left.left.value === 'arguments') {\n                        warning('Bad assignment.', that);\n                    }\n                    that.right = expression(19);\n                    return that;\n                } else if (left.identifier && !left.reserved) {\n                    if (funct[left.value] === 'exception') {\n                        warning(\"Do not assign to the exception parameter.\", left);\n                    }\n                    that.right = expression(19);\n                    return that;\n                }\n                if (left === syntax['function']) {\n                    warning(\n\"Expected an identifier in an assignment and instead saw a function invocation.\",\n                                token);\n                }\n            }\n            error(\"Bad assignment.\", that);\n        }, 20);\n    }\n\n\n    function bitwise(s, f, p) {\n        var x = symbol(s, p);\n        reserveName(x);\n        x.led = (typeof f === 'function') ? f : function (left) {\n            if (option.bitwise) {\n                warning(\"Unexpected use of '{a}'.\", this, this.id);\n            }\n            this.left = left;\n            this.right = expression(p);\n            return this;\n        };\n        return x;\n    }\n\n\n    function bitwiseassignop(s) {\n        symbol(s, 20).exps = true;\n        return infix(s, function (left, that) {\n            if (option.bitwise) {\n                warning(\"Unexpected use of '{a}'.\", that, that.id);\n            }\n            nonadjacent(prevtoken, token);\n            nonadjacent(token, nexttoken);\n            if (left) {\n                if (left.id === '.' || left.id === '[' ||\n                        (left.identifier && !left.reserved)) {\n                    expression(19);\n                    return that;\n                }\n                if (left === syntax['function']) {\n                    warning(\n\"Expected an identifier in an assignment, and instead saw a function invocation.\",\n                                token);\n                }\n                return that;\n            }\n            error(\"Bad assignment.\", that);\n        }, 20);\n    }\n\n\n    function suffix(s, f) {\n        var x = symbol(s, 150);\n        x.led = function (left) {\n            if (option.plusplus) {\n                warning(\"Unexpected use of '{a}'.\", this, this.id);\n            } else if ((!left.identifier || left.reserved) &&\n                    left.id !== '.' && left.id !== '[') {\n                warning(\"Bad operand.\", this);\n            }\n            this.left = left;\n            return this;\n        };\n        return x;\n    }\n\n\n    function optionalidentifier() {\n        if (nexttoken.identifier) {\n            advance();\n            if (option.safe && banned[token.value]) {\n                warning(\"ADsafe violation: '{a}'.\", token, token.value);\n            } else if (token.reserved && !option.es5) {\n                warning(\"Expected an identifier and instead saw '{a}' (a reserved word).\",\n                        token, token.id);\n            }\n            return token.value;\n        }\n    }\n\n\n    function identifier() {\n        var i = optionalidentifier();\n        if (i) {\n            return i;\n        }\n        if (token.id === 'function' && nexttoken.id === '(') {\n            warning(\"Missing name in function statement.\");\n        } else {\n            error(\"Expected an identifier and instead saw '{a}'.\",\n                    nexttoken, nexttoken.value);\n        }\n    }\n\n\n    function reachable(s) {\n        var i = 0, t;\n        if (nexttoken.id !== ';' || noreach) {\n            return;\n        }\n        for (;;) {\n            t = peek(i);\n            if (t.reach) {\n                return;\n            }\n            if (t.id !== '(endline)') {\n                if (t.id === 'function') {\n                    warning(\n\"Inner functions should be listed at the top of the outer function.\", t);\n                    break;\n                }\n                warning(\"Unreachable '{a}' after '{b}'.\", t, t.value, s);\n                break;\n            }\n            i += 1;\n        }\n    }\n\n\n    function statement(noindent) {\n        var i = indent, r, s = scope, t = nexttoken;\n\n// We don't like the empty statement.\n\n        if (t.id === ';') {\n            warning(\"Unnecessary semicolon.\", t);\n            advance(';');\n            return;\n        }\n\n// Is this a labelled statement?\n\n        if (t.identifier && !t.reserved && peek().id === ':') {\n            advance();\n            advance(':');\n            scope = Object.create(s);\n            addlabel(t.value, 'label');\n            if (!nexttoken.labelled) {\n                warning(\"Label '{a}' on {b} statement.\",\n                        nexttoken, t.value, nexttoken.value);\n            }\n            if (jx.test(t.value + ':')) {\n                warning(\"Label '{a}' looks like a javascript url.\",\n                        t, t.value);\n            }\n            nexttoken.label = t.value;\n            t = nexttoken;\n        }\n\n// Parse the statement.\n\n        if (!noindent) {\n            indentation();\n        }\n        r = expression(0, true);\n\n// Look for the final semicolon.\n\n        if (!t.block) {\n            if (!r || !r.exps) {\n                warning(\"Expected an assignment or function call and instead saw an expression.\", token);\n            } else if (option.nonew && r.id === '(' && r.left.id === 'new') {\n                warning(\"Do not use 'new' for side effects.\");\n            }\n            if (nexttoken.id !== ';') {\n                warningAt(\"Missing semicolon.\", token.line, token.from + token.value.length);\n            } else {\n                adjacent(token, nexttoken);\n                advance(';');\n                nonadjacent(token, nexttoken);\n            }\n        }\n\n// Restore the indentation.\n\n        indent = i;\n        scope = s;\n        return r;\n    }\n\n\n    function use_strict() {\n        if (nexttoken.value === 'use strict') {\n            if (strict_mode) {\n                warning(\"Unnecessary \\\"use strict\\\".\");\n            }\n            advance();\n            advance(';');\n            strict_mode = true;\n            option.newcap = true;\n            option.undef = true;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n\n    function statements(begin) {\n        var a = [], f, p;\n        if (option.adsafe) {\n            switch (begin) {\n            case 'script':\n\n// JSHint is also the static analizer for ADsafe. See www.ADsafe.org.\n\n                if (!adsafe_may) {\n                    if (nexttoken.value !== 'ADSAFE' ||\n                            peek(0).id !== '.' ||\n                            (peek(1).value !== 'id' &&\n                            peek(1).value !== 'go')) {\n                        error('ADsafe violation: Missing ADSAFE.id or ADSAFE.go.',\n                            nexttoken);\n                    }\n                }\n                if (nexttoken.value === 'ADSAFE' &&\n                        peek(0).id === '.' &&\n                        peek(1).value === 'id') {\n                    if (adsafe_may) {\n                        error('ADsafe violation.', nexttoken);\n                    }\n                    advance('ADSAFE');\n                    advance('.');\n                    advance('id');\n                    advance('(');\n                    if (nexttoken.value !== adsafe_id) {\n                        error('ADsafe violation: id does not match.', nexttoken);\n                    }\n                    advance('(string)');\n                    advance(')');\n                    advance(';');\n                    adsafe_may = true;\n                }\n                break;\n            case 'lib':\n                if (nexttoken.value === 'ADSAFE') {\n                    advance('ADSAFE');\n                    advance('.');\n                    advance('lib');\n                    advance('(');\n                    advance('(string)');\n                    comma();\n                    f = expression(0);\n                    if (f.id !== 'function') {\n                        error('The second argument to lib must be a function.', f);\n                    }\n                    p = f.funct['(params)'];\n                    p = p && p.join(', ');\n                    if (p && p !== 'lib') {\n                        error(\"Expected '{a}' and instead saw '{b}'.\",\n                            f, '(lib)', '(' + p + ')');\n                    }\n                    advance(')');\n                    advance(';');\n                    return a;\n                } else {\n                    error(\"ADsafe lib violation.\");\n                }\n            }\n        }\n        while (!nexttoken.reach && nexttoken.id !== '(end)') {\n            if (nexttoken.id === ';') {\n                warning(\"Unnecessary semicolon.\");\n                advance(';');\n            } else {\n                a.push(statement());\n            }\n        }\n        return a;\n    }\n\n\n    /*\n     * Parses a single block. A block is a sequence of statements wrapped in\n     * braces.\n     * \n     * ordinary - true for everything but function bodies and try blocks. \n     * stmt     - true if block can be a single statement (e.g. in if/for/while).     \n     */ \n    function block(ordinary, stmt) {\n        var a,\n            b = inblock,\n            old_indent = indent,\n            m = strict_mode,\n            s = scope,\n            t;\n\n        inblock = ordinary;\n        scope = Object.create(scope);\n        nonadjacent(token, nexttoken);\n        t = nexttoken;\n\n        if (nexttoken.id === '{') {\n            advance('{');\n            if (nexttoken.id !== '}' || token.line !== nexttoken.line) {\n                indent += option.indent;\n                while (!ordinary && nexttoken.from > indent) {\n                    indent += option.indent;\n                }\n                if (!ordinary && !use_strict() && !m && option.strict &&\n                        funct['(context)']['(global)']) {\n                    warning(\"Missing \\\"use strict\\\" statement.\");\n                }\n                a = statements();\n                strict_mode = m;\n                indent -= option.indent;\n                indentation();\n            }\n            advance('}', t);\n            indent = old_indent;\n        } else if (!ordinary) {\n            error(\"Expected '{a}' and instead saw '{b}'.\",\n                  nexttoken, '{', nexttoken.value);\n        } else {\n            if (!stmt || option.curly)\n                warning(\"Expected '{a}' and instead saw '{b}'.\",\n                        nexttoken, '{', nexttoken.value);\n\n            noreach = true;\n            a = [statement()];\n            noreach = false;\n        }\n        funct['(verb)'] = null;\n        scope = s;\n        inblock = b;\n        if (ordinary && option.noempty && (!a || a.length === 0)) {\n            warning(\"Empty block.\");\n        }\n        return a;\n    }\n\n\n    function countMember(m) {\n        if (membersOnly && typeof membersOnly[m] !== 'boolean') {\n            warning(\"Unexpected /*member '{a}'.\", token, m);\n        }\n        if (typeof member[m] === 'number') {\n            member[m] += 1;\n        } else {\n            member[m] = 1;\n        }\n    }\n\n\n    function note_implied(token) {\n        var name = token.value, line = token.line, a = implied[name];\n        if (typeof a === 'function') {\n            a = false;\n        }\n        if (!a) {\n            a = [line];\n            implied[name] = a;\n        } else if (a[a.length - 1] !== line) {\n            a.push(line);\n        }\n    }\n\n\n// CSS parsing.\n\n    function cssName() {\n        if (nexttoken.identifier) {\n            advance();\n            return true;\n        }\n    }\n\n\n    function cssNumber() {\n        if (nexttoken.id === '-') {\n            advance('-');\n            adjacent();\n            nolinebreak();\n        }\n        if (nexttoken.type === '(number)') {\n            advance('(number)');\n            return true;\n        }\n    }\n\n\n    function cssString() {\n        if (nexttoken.type === '(string)') {\n            advance();\n            return true;\n        }\n    }\n\n\n    function cssColor() {\n        var i, number, value;\n        if (nexttoken.identifier) {\n            value = nexttoken.value;\n            if (value === 'rgb' || value === 'rgba') {\n                advance();\n                advance('(');\n                for (i = 0; i < 3; i += 1) {\n                    if (i) {\n                        advance(',');\n                    }\n                    number = nexttoken.value;\n                    if (nexttoken.type !== '(number)' || number < 0) {\n                        warning(\"Expected a positive number and instead saw '{a}'\",\n                            nexttoken, number);\n                        advance();\n                    } else {\n                        advance();\n                        if (nexttoken.id === '%') {\n                            advance('%');\n                            if (number > 100) {\n                                warning(\"Expected a percentage and instead saw '{a}'\",\n                                    token, number);\n                            }\n                        } else {\n                            if (number > 255) {\n                                warning(\"Expected a small number and instead saw '{a}'\",\n                                    token, number);\n                            }\n                        }\n                    }\n                }\n                if (value === 'rgba') {\n                    advance(',');\n                    number = +nexttoken.value;\n                    if (nexttoken.type !== '(number)' || number < 0 || number > 1) {\n                        warning(\"Expected a number between 0 and 1 and instead saw '{a}'\",\n                            nexttoken, number);\n                    }\n                    advance();\n                    if (nexttoken.id === '%') {\n                        warning(\"Unexpected '%'.\");\n                        advance('%');\n                    }\n                }\n                advance(')');\n                return true;\n            } else if (cssColorData[nexttoken.value] === true) {\n                advance();\n                return true;\n            }\n        } else if (nexttoken.type === '(color)') {\n            advance();\n            return true;\n        }\n        return false;\n    }\n\n\n    function cssLength() {\n        if (nexttoken.id === '-') {\n            advance('-');\n            adjacent();\n            nolinebreak();\n        }\n        if (nexttoken.type === '(number)') {\n            advance();\n            if (nexttoken.type !== '(string)' &&\n                    cssLengthData[nexttoken.value] === true) {\n                adjacent();\n                advance();\n            } else if (+token.value !== 0) {\n                warning(\"Expected a linear unit and instead saw '{a}'.\",\n                    nexttoken, nexttoken.value);\n            }\n            return true;\n        }\n        return false;\n    }\n\n\n    function cssLineHeight() {\n        if (nexttoken.id === '-') {\n            advance('-');\n            adjacent();\n        }\n        if (nexttoken.type === '(number)') {\n            advance();\n            if (nexttoken.type !== '(string)' &&\n                    cssLengthData[nexttoken.value] === true) {\n                adjacent();\n                advance();\n            }\n            return true;\n        }\n        return false;\n    }\n\n\n    function cssWidth() {\n        if (nexttoken.identifier) {\n            switch (nexttoken.value) {\n            case 'thin':\n            case 'medium':\n            case 'thick':\n                advance();\n                return true;\n            }\n        } else {\n            return cssLength();\n        }\n    }\n\n\n    function cssMargin() {\n        if (nexttoken.identifier) {\n            if (nexttoken.value === 'auto') {\n                advance();\n                return true;\n            }\n        } else {\n            return cssLength();\n        }\n    }\n\n    function cssAttr() {\n        if (nexttoken.identifier && nexttoken.value === 'attr') {\n            advance();\n            advance('(');\n            if (!nexttoken.identifier) {\n                warning(\"Expected a name and instead saw '{a}'.\",\n                        nexttoken, nexttoken.value);\n            }\n            advance();\n            advance(')');\n            return true;\n        }\n        return false;\n    }\n\n\n    function cssCommaList() {\n        while (nexttoken.id !== ';') {\n            if (!cssName() && !cssString()) {\n                warning(\"Expected a name and instead saw '{a}'.\",\n                        nexttoken, nexttoken.value);\n            }\n            if (nexttoken.id !== ',') {\n                return true;\n            }\n            comma();\n        }\n    }\n\n\n    function cssCounter() {\n        if (nexttoken.identifier && nexttoken.value === 'counter') {\n            advance();\n            advance('(');\n            advance();\n            if (nexttoken.id === ',') {\n                comma();\n                if (nexttoken.type !== '(string)') {\n                    warning(\"Expected a string and instead saw '{a}'.\",\n                        nexttoken, nexttoken.value);\n                }\n                advance();\n            }\n            advance(')');\n            return true;\n        }\n        if (nexttoken.identifier && nexttoken.value === 'counters') {\n            advance();\n            advance('(');\n            if (!nexttoken.identifier) {\n                warning(\"Expected a name and instead saw '{a}'.\",\n                        nexttoken, nexttoken.value);\n            }\n            advance();\n            if (nexttoken.id === ',') {\n                comma();\n                if (nexttoken.type !== '(string)') {\n                    warning(\"Expected a string and instead saw '{a}'.\",\n                        nexttoken, nexttoken.value);\n                }\n                advance();\n            }\n            if (nexttoken.id === ',') {\n                comma();\n                if (nexttoken.type !== '(string)') {\n                    warning(\"Expected a string and instead saw '{a}'.\",\n                        nexttoken, nexttoken.value);\n                }\n                advance();\n            }\n            advance(')');\n            return true;\n        }\n        return false;\n    }\n\n\n    function cssShape() {\n        var i;\n        if (nexttoken.identifier && nexttoken.value === 'rect') {\n            advance();\n            advance('(');\n            for (i = 0; i < 4; i += 1) {\n                if (!cssLength()) {\n                    warning(\"Expected a number and instead saw '{a}'.\",\n                        nexttoken, nexttoken.value);\n                    break;\n                }\n            }\n            advance(')');\n            return true;\n        }\n        return false;\n    }\n\n\n    function cssUrl() {\n        var c, url;\n        if (nexttoken.identifier && nexttoken.value === 'url') {\n            nexttoken = lex.range('(', ')');\n            url = nexttoken.value;\n            c = url.charAt(0);\n            if (c === '\"' || c === '\\'') {\n                if (url.slice(-1) !== c) {\n                    warning(\"Bad url string.\");\n                } else {\n                    url = url.slice(1, -1);\n                    if (url.indexOf(c) >= 0) {\n                        warning(\"Bad url string.\");\n                    }\n                }\n            }\n            if (!url) {\n                warning(\"Missing url.\");\n            }\n            advance();\n            if (option.safe && ux.test(url)) {\n                error(\"ADsafe URL violation.\");\n            }\n            urls.push(url);\n            return true;\n        }\n        return false;\n    }\n\n\n    cssAny = [cssUrl, function () {\n        for (;;) {\n            if (nexttoken.identifier) {\n                switch (nexttoken.value.toLowerCase()) {\n                case 'url':\n                    cssUrl();\n                    break;\n                case 'expression':\n                    warning(\"Unexpected expression '{a}'.\",\n                        nexttoken, nexttoken.value);\n                    advance();\n                    break;\n                default:\n                    advance();\n                }\n            } else {\n                if (nexttoken.id === ';' || nexttoken.id === '!'  ||\n                        nexttoken.id === '(end)' || nexttoken.id === '}') {\n                    return true;\n                }\n                advance();\n            }\n        }\n    }];\n\n\n    cssBorderStyle = [\n        'none', 'dashed', 'dotted', 'double', 'groove',\n        'hidden', 'inset', 'outset', 'ridge', 'solid'\n    ];\n\n    cssBreak = [\n        'auto', 'always', 'avoid', 'left', 'right'\n    ];\n\n    cssMedia = {\n        'all': true,\n        'braille': true,\n        'embossed': true,\n        'handheld': true,\n        'print': true,\n        'projection': true,\n        'screen': true,\n        'speech': true,\n        'tty': true,\n        'tv': true\n    };\n\n    cssOverflow = [\n        'auto', 'hidden', 'scroll', 'visible'\n    ];\n\n    cssAttributeData = {\n        background: [\n            true, 'background-attachment', 'background-color',\n            'background-image', 'background-position', 'background-repeat'\n        ],\n        'background-attachment': ['scroll', 'fixed'],\n        'background-color': ['transparent', cssColor],\n        'background-image': ['none', cssUrl],\n        'background-position': [\n            2, [cssLength, 'top', 'bottom', 'left', 'right', 'center']\n        ],\n        'background-repeat': [\n            'repeat', 'repeat-x', 'repeat-y', 'no-repeat'\n        ],\n        'border': [true, 'border-color', 'border-style', 'border-width'],\n        'border-bottom': [\n            true, 'border-bottom-color', 'border-bottom-style',\n            'border-bottom-width'\n        ],\n        'border-bottom-color': cssColor,\n        'border-bottom-style': cssBorderStyle,\n        'border-bottom-width': cssWidth,\n        'border-collapse': ['collapse', 'separate'],\n        'border-color': ['transparent', 4, cssColor],\n        'border-left': [\n            true, 'border-left-color', 'border-left-style', 'border-left-width'\n        ],\n        'border-left-color': cssColor,\n        'border-left-style': cssBorderStyle,\n        'border-left-width': cssWidth,\n        'border-right': [\n            true, 'border-right-color', 'border-right-style',\n            'border-right-width'\n        ],\n        'border-right-color': cssColor,\n        'border-right-style': cssBorderStyle,\n        'border-right-width': cssWidth,\n        'border-spacing': [2, cssLength],\n        'border-style': [4, cssBorderStyle],\n        'border-top': [\n            true, 'border-top-color', 'border-top-style', 'border-top-width'\n        ],\n        'border-top-color': cssColor,\n        'border-top-style': cssBorderStyle,\n        'border-top-width': cssWidth,\n        'border-width': [4, cssWidth],\n        bottom: [cssLength, 'auto'],\n        'caption-side' : ['bottom', 'left', 'right', 'top'],\n        clear: ['both', 'left', 'none', 'right'],\n        clip: [cssShape, 'auto'],\n        color: cssColor,\n        content: [\n            'open-quote', 'close-quote', 'no-open-quote', 'no-close-quote',\n            cssString, cssUrl, cssCounter, cssAttr\n        ],\n        'counter-increment': [\n            cssName, 'none'\n        ],\n        'counter-reset': [\n            cssName, 'none'\n        ],\n        cursor: [\n            cssUrl, 'auto', 'crosshair', 'default', 'e-resize', 'help', 'move',\n            'n-resize', 'ne-resize', 'nw-resize', 'pointer', 's-resize',\n            'se-resize', 'sw-resize', 'w-resize', 'text', 'wait'\n        ],\n        direction: ['ltr', 'rtl'],\n        display: [\n            'block', 'compact', 'inline', 'inline-block', 'inline-table',\n            'list-item', 'marker', 'none', 'run-in', 'table', 'table-caption',\n            'table-cell', 'table-column', 'table-column-group',\n            'table-footer-group', 'table-header-group', 'table-row',\n            'table-row-group'\n        ],\n        'empty-cells': ['show', 'hide'],\n        'float': ['left', 'none', 'right'],\n        font: [\n            'caption', 'icon', 'menu', 'message-box', 'small-caption',\n            'status-bar', true, 'font-size', 'font-style', 'font-weight',\n            'font-family'\n        ],\n        'font-family': cssCommaList,\n        'font-size': [\n            'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large',\n            'xx-large', 'larger', 'smaller', cssLength\n        ],\n        'font-size-adjust': ['none', cssNumber],\n        'font-stretch': [\n            'normal', 'wider', 'narrower', 'ultra-condensed',\n            'extra-condensed', 'condensed', 'semi-condensed',\n            'semi-expanded', 'expanded', 'extra-expanded'\n        ],\n        'font-style': [\n            'normal', 'italic', 'oblique'\n        ],\n        'font-variant': [\n            'normal', 'small-caps'\n        ],\n        'font-weight': [\n            'normal', 'bold', 'bolder', 'lighter', cssNumber\n        ],\n        height: [cssLength, 'auto'],\n        left: [cssLength, 'auto'],\n        'letter-spacing': ['normal', cssLength],\n        'line-height': ['normal', cssLineHeight],\n        'list-style': [\n            true, 'list-style-image', 'list-style-position', 'list-style-type'\n        ],\n        'list-style-image': ['none', cssUrl],\n        'list-style-position': ['inside', 'outside'],\n        'list-style-type': [\n            'circle', 'disc', 'square', 'decimal', 'decimal-leading-zero',\n            'lower-roman', 'upper-roman', 'lower-greek', 'lower-alpha',\n            'lower-latin', 'upper-alpha', 'upper-latin', 'hebrew', 'katakana',\n            'hiragana-iroha', 'katakana-oroha', 'none'\n        ],\n        margin: [4, cssMargin],\n        'margin-bottom': cssMargin,\n        'margin-left': cssMargin,\n        'margin-right': cssMargin,\n        'margin-top': cssMargin,\n        'marker-offset': [cssLength, 'auto'],\n        'max-height': [cssLength, 'none'],\n        'max-width': [cssLength, 'none'],\n        'min-height': cssLength,\n        'min-width': cssLength,\n        opacity: cssNumber,\n        outline: [true, 'outline-color', 'outline-style', 'outline-width'],\n        'outline-color': ['invert', cssColor],\n        'outline-style': [\n            'dashed', 'dotted', 'double', 'groove', 'inset', 'none',\n            'outset', 'ridge', 'solid'\n        ],\n        'outline-width': cssWidth,\n        overflow: cssOverflow,\n        'overflow-x': cssOverflow,\n        'overflow-y': cssOverflow,\n        padding: [4, cssLength],\n        'padding-bottom': cssLength,\n        'padding-left': cssLength,\n        'padding-right': cssLength,\n        'padding-top': cssLength,\n        'page-break-after': cssBreak,\n        'page-break-before': cssBreak,\n        position: ['absolute', 'fixed', 'relative', 'static'],\n        quotes: [8, cssString],\n        right: [cssLength, 'auto'],\n        'table-layout': ['auto', 'fixed'],\n        'text-align': ['center', 'justify', 'left', 'right'],\n        'text-decoration': [\n            'none', 'underline', 'overline', 'line-through', 'blink'\n        ],\n        'text-indent': cssLength,\n        'text-shadow': ['none', 4, [cssColor, cssLength]],\n        'text-transform': ['capitalize', 'uppercase', 'lowercase', 'none'],\n        top: [cssLength, 'auto'],\n        'unicode-bidi': ['normal', 'embed', 'bidi-override'],\n        'vertical-align': [\n            'baseline', 'bottom', 'sub', 'super', 'top', 'text-top', 'middle',\n            'text-bottom', cssLength\n        ],\n        visibility: ['visible', 'hidden', 'collapse'],\n        'white-space': [\n            'normal', 'nowrap', 'pre', 'pre-line', 'pre-wrap', 'inherit'\n        ],\n        width: [cssLength, 'auto'],\n        'word-spacing': ['normal', cssLength],\n        'word-wrap': ['break-word', 'normal'],\n        'z-index': ['auto', cssNumber]\n    };\n\n    function styleAttribute() {\n        var v;\n        while (nexttoken.id === '*' || nexttoken.id === '#' ||\n                nexttoken.value === '_') {\n            if (!option.css) {\n                warning(\"Unexpected '{a}'.\", nexttoken, nexttoken.value);\n            }\n            advance();\n        }\n        if (nexttoken.id === '-') {\n            if (!option.css) {\n                warning(\"Unexpected '{a}'.\", nexttoken, nexttoken.value);\n            }\n            advance('-');\n            if (!nexttoken.identifier) {\n                warning(\n\"Expected a non-standard style attribute and instead saw '{a}'.\",\n                    nexttoken, nexttoken.value);\n            }\n            advance();\n            return cssAny;\n        } else {\n            if (!nexttoken.identifier) {\n                warning(\"Excepted a style attribute, and instead saw '{a}'.\",\n                    nexttoken, nexttoken.value);\n            } else {\n                if (is_own(cssAttributeData, nexttoken.value)) {\n                    v = cssAttributeData[nexttoken.value];\n                } else {\n                    v = cssAny;\n                    if (!option.css) {\n                        warning(\"Unrecognized style attribute '{a}'.\",\n                                nexttoken, nexttoken.value);\n                    }\n                }\n            }\n            advance();\n            return v;\n        }\n    }\n\n\n    function styleValue(v) {\n        var i = 0,\n            n,\n            once,\n            match,\n            round,\n            start = 0,\n            vi;\n        switch (typeof v) {\n        case 'function':\n            return v();\n        case 'string':\n            if (nexttoken.identifier && nexttoken.value === v) {\n                advance();\n                return true;\n            }\n            return false;\n        }\n        for (;;) {\n            if (i >= v.length) {\n                return false;\n            }\n            vi = v[i];\n            i += 1;\n            if (vi === true) {\n                break;\n            } else if (typeof vi === 'number') {\n                n = vi;\n                vi = v[i];\n                i += 1;\n            } else {\n                n = 1;\n            }\n            match = false;\n            while (n > 0) {\n                if (styleValue(vi)) {\n                    match = true;\n                    n -= 1;\n                } else {\n                    break;\n                }\n            }\n            if (match) {\n                return true;\n            }\n        }\n        start = i;\n        once = [];\n        for (;;) {\n            round = false;\n            for (i = start; i < v.length; i += 1) {\n                if (!once[i]) {\n                    if (styleValue(cssAttributeData[v[i]])) {\n                        match = true;\n                        round = true;\n                        once[i] = true;\n                        break;\n                    }\n                }\n            }\n            if (!round) {\n                return match;\n            }\n        }\n    }\n\n    function styleChild() {\n        if (nexttoken.id === '(number)') {\n            advance();\n            if (nexttoken.value === 'n' && nexttoken.identifier) {\n                adjacent();\n                advance();\n                if (nexttoken.id === '+') {\n                    adjacent();\n                    advance('+');\n                    adjacent();\n                    advance('(number)');\n                }\n            }\n            return;\n        } else {\n            switch (nexttoken.value) {\n            case 'odd':\n            case 'even':\n                if (nexttoken.identifier) {\n                    advance();\n                    return;\n                }\n            }\n        }\n        warning(\"Unexpected token '{a}'.\", nexttoken, nexttoken.value);\n    }\n\n    function substyle() {\n        var v;\n        for (;;) {\n            if (nexttoken.id === '}' || nexttoken.id === '(end)' ||\n                    xquote && nexttoken.id === xquote) {\n                return;\n            }\n            while (nexttoken.id === ';') {\n                warning(\"Misplaced ';'.\");\n                advance(';');\n            }\n            v = styleAttribute();\n            advance(':');\n            if (nexttoken.identifier && nexttoken.value === 'inherit') {\n                advance();\n            } else {\n                if (!styleValue(v)) {\n                    warning(\"Unexpected token '{a}'.\", nexttoken,\n                        nexttoken.value);\n                    advance();\n                }\n            }\n            if (nexttoken.id === '!') {\n                advance('!');\n                adjacent();\n                if (nexttoken.identifier && nexttoken.value === 'important') {\n                    advance();\n                } else {\n                    warning(\"Expected '{a}' and instead saw '{b}'.\",\n                        nexttoken, 'important', nexttoken.value);\n                }\n            }\n            if (nexttoken.id === '}' || nexttoken.id === xquote) {\n                warning(\"Missing '{a}'.\", nexttoken, ';');\n            } else {\n                advance(';');\n            }\n        }\n    }\n\n    function styleSelector() {\n        if (nexttoken.identifier) {\n            if (!is_own(htmltag, option.cap ?\n                    nexttoken.value.toLowerCase() : nexttoken.value)) {\n                warning(\"Expected a tagName, and instead saw {a}.\",\n                    nexttoken, nexttoken.value);\n            }\n            advance();\n        } else {\n            switch (nexttoken.id) {\n            case '>':\n            case '+':\n                advance();\n                styleSelector();\n                break;\n            case ':':\n                advance(':');\n                switch (nexttoken.value) {\n                case 'active':\n                case 'after':\n                case 'before':\n                case 'checked':\n                case 'disabled':\n                case 'empty':\n                case 'enabled':\n                case 'first-child':\n                case 'first-letter':\n                case 'first-line':\n                case 'first-of-type':\n                case 'focus':\n                case 'hover':\n                case 'last-child':\n                case 'last-of-type':\n                case 'link':\n                case 'only-of-type':\n                case 'root':\n                case 'target':\n                case 'visited':\n                    advance();\n                    break;\n                case 'lang':\n                    advance();\n                    advance('(');\n                    if (!nexttoken.identifier) {\n                        warning(\"Expected a lang code, and instead saw :{a}.\",\n                            nexttoken, nexttoken.value);\n                    }\n                    advance(')');\n                    break;\n                case 'nth-child':\n                case 'nth-last-child':\n                case 'nth-last-of-type':\n                case 'nth-of-type':\n                    advance();\n                    advance('(');\n                    styleChild();\n                    advance(')');\n                    break;\n                case 'not':\n                    advance();\n                    advance('(');\n                    if (nexttoken.id === ':' && peek(0).value === 'not') {\n                        warning(\"Nested not.\");\n                    }\n                    styleSelector();\n                    advance(')');\n                    break;\n                default:\n                    warning(\"Expected a pseudo, and instead saw :{a}.\",\n                        nexttoken, nexttoken.value);\n                }\n                break;\n            case '#':\n                advance('#');\n                if (!nexttoken.identifier) {\n                    warning(\"Expected an id, and instead saw #{a}.\",\n                        nexttoken, nexttoken.value);\n                }\n                advance();\n                break;\n            case '*':\n                advance('*');\n                break;\n            case '.':\n                advance('.');\n                if (!nexttoken.identifier) {\n                    warning(\"Expected a class, and instead saw #.{a}.\",\n                        nexttoken, nexttoken.value);\n                }\n                advance();\n                break;\n            case '[':\n                advance('[');\n                if (!nexttoken.identifier) {\n                    warning(\"Expected an attribute, and instead saw [{a}].\",\n                        nexttoken, nexttoken.value);\n                }\n                advance();\n                if (nexttoken.id === '=' || nexttoken.value === '~=' ||\n                        nexttoken.value === '$=' ||\n                        nexttoken.value === '|=' ||\n                        nexttoken.id === '*=' ||\n                        nexttoken.id === '^=') {\n                    advance();\n                    if (nexttoken.type !== '(string)') {\n                        warning(\"Expected a string, and instead saw {a}.\",\n                            nexttoken, nexttoken.value);\n                    }\n                    advance();\n                }\n                advance(']');\n                break;\n            default:\n                error(\"Expected a CSS selector, and instead saw {a}.\",\n                    nexttoken, nexttoken.value);\n            }\n        }\n    }\n\n    function stylePattern() {\n        if (nexttoken.id === '{') {\n            warning(\"Expected a style pattern, and instead saw '{a}'.\", nexttoken,\n                nexttoken.id);\n        }\n        for (;;) {\n            styleSelector();\n            if (nexttoken.id === '</' || nexttoken.id === '{' ||\n                    nexttoken.id === '(end)') {\n                return '';\n            }\n            if (nexttoken.id === ',') {\n                comma();\n            }\n        }\n    }\n\n    function stylelist() {\n        while (nexttoken.id !== '</' && nexttoken.id !== '(end)') {\n            stylePattern();\n            xmode = 'styleproperty';\n            if (nexttoken.id === ';') {\n                advance(';');\n            } else {\n                advance('{');\n                substyle();\n                xmode = 'style';\n                advance('}');\n            }\n        }\n    }\n\n    function styles() {\n        var i;\n        while (nexttoken.id === '@') {\n            i = peek();\n            advance('@');\n            if (nexttoken.identifier) {\n                switch (nexttoken.value) {\n                case 'import':\n                    advance();\n                    if (!cssUrl()) {\n                        warning(\"Expected '{a}' and instead saw '{b}'.\",\n                            nexttoken, 'url', nexttoken.value);\n                        advance();\n                    }\n                    advance(';');\n                    break;\n                case 'media':\n                    advance();\n                    for (;;) {\n                        if (!nexttoken.identifier || cssMedia[nexttoken.value] === true) {\n                            error(\"Expected a CSS media type, and instead saw '{a}'.\", nexttoken, nexttoken.id);\n                        }\n                        advance();\n                        if (nexttoken.id !== ',') {\n                            break;\n                        }\n                        advance(',');\n                    }\n                    advance('{');\n                    stylelist();\n                    advance('}');\n                    break;\n                default:\n                    warning(\"Expected an at-rule, and instead saw @{a}.\",\n                        nexttoken, nexttoken.value);\n                }\n            } else {\n                warning(\"Expected an at-rule, and instead saw '{a}'.\",\n                    nexttoken, nexttoken.value);\n            }\n        }\n        stylelist();\n    }\n\n\n// HTML parsing.\n\n    function doBegin(n) {\n        if (n !== 'html' && !option.fragment) {\n            if (n === 'div' && option.adsafe) {\n                error(\"ADSAFE: Use the fragment option.\");\n            } else {\n                error(\"Expected '{a}' and instead saw '{b}'.\",\n                    token, 'html', n);\n            }\n        }\n        if (option.adsafe) {\n            if (n === 'html') {\n                error(\n\"Currently, ADsafe does not operate on whole HTML documents. It operates on <div> fragments and .js files.\", token);\n            }\n            if (option.fragment) {\n                if (n !== 'div') {\n                    error(\"ADsafe violation: Wrap the widget in a div.\", token);\n                }\n            } else {\n                error(\"Use the fragment option.\", token);\n            }\n        }\n        option.browser = true;\n        assume();\n    }\n\n    function doAttribute(n, a, v) {\n        var u, x;\n        if (a === 'id') {\n            u = typeof v === 'string' ? v.toUpperCase() : '';\n            if (ids[u] === true) {\n                warning(\"Duplicate id='{a}'.\", nexttoken, v);\n            }\n            if (!/^[A-Za-z][A-Za-z0-9._:\\-]*$/.test(v)) {\n                warning(\"Bad id: '{a}'.\", nexttoken, v);\n            } else if (option.adsafe) {\n                if (adsafe_id) {\n                    if (v.slice(0, adsafe_id.length) !== adsafe_id) {\n                        warning(\"ADsafe violation: An id must have a '{a}' prefix\",\n                                nexttoken, adsafe_id);\n                    } else if (!/^[A-Z]+_[A-Z]+$/.test(v)) {\n                        warning(\"ADSAFE violation: bad id.\");\n                    }\n                } else {\n                    adsafe_id = v;\n                    if (!/^[A-Z]+_$/.test(v)) {\n                        warning(\"ADSAFE violation: bad id.\");\n                    }\n                }\n            }\n            x = v.search(dx);\n            if (x >= 0) {\n                warning(\"Unexpected character '{a}' in {b}.\", token, v.charAt(x), a);\n            }\n            ids[u] = true;\n        } else if (a === 'class' || a === 'type' || a === 'name') {\n            x = v.search(qx);\n            if (x >= 0) {\n                warning(\"Unexpected character '{a}' in {b}.\", token, v.charAt(x), a);\n            }\n            ids[u] = true;\n        } else if (a === 'href' || a === 'background' ||\n                a === 'content' || a === 'data' ||\n                a.indexOf('src') >= 0 || a.indexOf('url') >= 0) {\n            if (option.safe && ux.test(v)) {\n                error(\"ADsafe URL violation.\");\n            }\n            urls.push(v);\n        } else if (a === 'for') {\n            if (option.adsafe) {\n                if (adsafe_id) {\n                    if (v.slice(0, adsafe_id.length) !== adsafe_id) {\n                        warning(\"ADsafe violation: An id must have a '{a}' prefix\",\n                                nexttoken, adsafe_id);\n                    } else if (!/^[A-Z]+_[A-Z]+$/.test(v)) {\n                        warning(\"ADSAFE violation: bad id.\");\n                    }\n                } else {\n                    warning(\"ADSAFE violation: bad id.\");\n                }\n            }\n        } else if (a === 'name') {\n            if (option.adsafe && v.indexOf('_') >= 0) {\n                warning(\"ADsafe name violation.\");\n            }\n        }\n    }\n\n    function doTag(n, a) {\n        var i, t = htmltag[n], x;\n        src = false;\n        if (!t) {\n            error(\"Unrecognized tag '<{a}>'.\",\n                    nexttoken,\n                    n === n.toLowerCase() ? n :\n                        n + ' (capitalization error)');\n        }\n        if (stack.length > 0) {\n            if (n === 'html') {\n                error(\"Too many <html> tags.\", token);\n            }\n            x = t.parent;\n            if (x) {\n                if (x.indexOf(' ' + stack[stack.length - 1].name + ' ') < 0) {\n                    error(\"A '<{a}>' must be within '<{b}>'.\",\n                            token, n, x);\n                }\n            } else if (!option.adsafe && !option.fragment) {\n                i = stack.length;\n                do {\n                    if (i <= 0) {\n                        error(\"A '<{a}>' must be within '<{b}>'.\",\n                                token, n, 'body');\n                    }\n                    i -= 1;\n                } while (stack[i].name !== 'body');\n            }\n        }\n        switch (n) {\n        case 'div':\n            if (option.adsafe && stack.length === 1 && !adsafe_id) {\n                warning(\"ADSAFE violation: missing ID_.\");\n            }\n            break;\n        case 'script':\n            xmode = 'script';\n            advance('>');\n            indent = nexttoken.from;\n            if (a.lang) {\n                warning(\"lang is deprecated.\", token);\n            }\n            if (option.adsafe && stack.length !== 1) {\n                warning(\"ADsafe script placement violation.\", token);\n            }\n            if (a.src) {\n                if (option.adsafe && (!adsafe_may || !approved[a.src])) {\n                    warning(\"ADsafe unapproved script source.\", token);\n                }\n                if (a.type) {\n                    warning(\"type is unnecessary.\", token);\n                }\n            } else {\n                if (adsafe_went) {\n                    error(\"ADsafe script violation.\", token);\n                }\n                use_strict();\n                statements('script');\n            }\n            xmode = 'html';\n            advance('</');\n            if (!nexttoken.identifier && nexttoken.value !== 'script') {\n                warning(\"Expected '{a}' and instead saw '{b}'.\",\n                        nexttoken, 'script', nexttoken.value);\n            }\n            advance();\n            xmode = 'outer';\n            break;\n        case 'style':\n            xmode = 'style';\n            advance('>');\n            styles();\n            xmode = 'html';\n            advance('</');\n            if (!nexttoken.identifier && nexttoken.value !== 'style') {\n                warning(\"Expected '{a}' and instead saw '{b}'.\",\n                        nexttoken, 'style', nexttoken.value);\n            }\n            advance();\n            xmode = 'outer';\n            break;\n        case 'input':\n            switch (a.type) {\n            case 'radio':\n            case 'checkbox':\n            case 'button':\n            case 'reset':\n            case 'submit':\n                break;\n            case 'text':\n            case 'file':\n            case 'password':\n            case 'file':\n            case 'hidden':\n            case 'image':\n                if (option.adsafe && a.autocomplete !== 'off') {\n                    warning(\"ADsafe autocomplete violation.\");\n                }\n                break;\n            default:\n                warning(\"Bad input type.\");\n            }\n            break;\n        case 'applet':\n        case 'body':\n        case 'embed':\n        case 'frame':\n        case 'frameset':\n        case 'head':\n        case 'iframe':\n        case 'noembed':\n        case 'noframes':\n        case 'object':\n        case 'param':\n            if (option.adsafe) {\n                warning(\"ADsafe violation: Disallowed tag: \" + n);\n            }\n            break;\n        }\n    }\n\n\n    function closetag(n) {\n        return '</' + n + '>';\n    }\n\n    function html() {\n        var a, attributes, e, n, q, t, v, w = option.white, wmode;\n        xmode = 'html';\n        xquote = '';\n        stack = null;\n        for (;;) {\n            switch (nexttoken.value) {\n            case '<':\n                xmode = 'html';\n                advance('<');\n                attributes = {};\n                t = nexttoken;\n                if (!t.identifier) {\n                    warning(\"Bad identifier {a}.\", t, t.value);\n                }\n                n = t.value;\n                if (option.cap) {\n                    n = n.toLowerCase();\n                }\n                t.name = n;\n                advance();\n                if (!stack) {\n                    stack = [];\n                    doBegin(n);\n                }\n                v = htmltag[n];\n                if (typeof v !== 'object') {\n                    error(\"Unrecognized tag '<{a}>'.\", t, n);\n                }\n                e = v.empty;\n                t.type = n;\n                for (;;) {\n                    if (nexttoken.id === '/') {\n                        advance('/');\n                        if (nexttoken.id !== '>') {\n                            warning(\"Expected '{a}' and instead saw '{b}'.\",\n                                    nexttoken, '>', nexttoken.value);\n                        }\n                        break;\n                    }\n                    if (nexttoken.id && nexttoken.id.substr(0, 1) === '>') {\n                        break;\n                    }\n                    if (!nexttoken.identifier) {\n                        if (nexttoken.id === '(end)' || nexttoken.id === '(error)') {\n                            error(\"Missing '>'.\", nexttoken);\n                        }\n                        warning(\"Bad identifier.\");\n                    }\n                    option.white = true;\n                    nonadjacent(token, nexttoken);\n                    a = nexttoken.value;\n                    option.white = w;\n                    advance();\n                    if (!option.cap && a !== a.toLowerCase()) {\n                        warning(\"Attribute '{a}' not all lower case.\", nexttoken, a);\n                    }\n                    a = a.toLowerCase();\n                    xquote = '';\n                    if (is_own(attributes, a)) {\n                        warning(\"Attribute '{a}' repeated.\", nexttoken, a);\n                    }\n                    if (a.slice(0, 2) === 'on') {\n                        if (!option.on) {\n                            warning(\"Avoid HTML event handlers.\");\n                        }\n                        xmode = 'scriptstring';\n                        advance('=');\n                        q = nexttoken.id;\n                        if (q !== '\"' && q !== \"'\") {\n                            error(\"Missing quote.\");\n                        }\n                        xquote = q;\n                        wmode = option.white;\n                        option.white = false;\n                        advance(q);\n                        use_strict();\n                        statements('on');\n                        option.white = wmode;\n                        if (nexttoken.id !== q) {\n                            error(\"Missing close quote on script attribute.\");\n                        }\n                        xmode = 'html';\n                        xquote = '';\n                        advance(q);\n                        v = false;\n                    } else if (a === 'style') {\n                        xmode = 'scriptstring';\n                        advance('=');\n                        q = nexttoken.id;\n                        if (q !== '\"' && q !== \"'\") {\n                            error(\"Missing quote.\");\n                        }\n                        xmode = 'styleproperty';\n                        xquote = q;\n                        advance(q);\n                        substyle();\n                        xmode = 'html';\n                        xquote = '';\n                        advance(q);\n                        v = false;\n                    } else {\n                        if (nexttoken.id === '=') {\n                            advance('=');\n                            v = nexttoken.value;\n                            if (!nexttoken.identifier &&\n                                    nexttoken.id !== '\"' &&\n                                    nexttoken.id !== '\\'' &&\n                                    nexttoken.type !== '(string)' &&\n                                    nexttoken.type !== '(number)' &&\n                                    nexttoken.type !== '(color)') {\n                                warning(\"Expected an attribute value and instead saw '{a}'.\", token, a);\n                            }\n                            advance();\n                        } else {\n                            v = true;\n                        }\n                    }\n                    attributes[a] = v;\n                    doAttribute(n, a, v);\n                }\n                doTag(n, attributes);\n                if (!e) {\n                    stack.push(t);\n                }\n                xmode = 'outer';\n                advance('>');\n                break;\n            case '</':\n                xmode = 'html';\n                advance('</');\n                if (!nexttoken.identifier) {\n                    warning(\"Bad identifier.\");\n                }\n                n = nexttoken.value;\n                if (option.cap) {\n                    n = n.toLowerCase();\n                }\n                advance();\n                if (!stack) {\n                    error(\"Unexpected '{a}'.\", nexttoken, closetag(n));\n                }\n                t = stack.pop();\n                if (!t) {\n                    error(\"Unexpected '{a}'.\", nexttoken, closetag(n));\n                }\n                if (t.name !== n) {\n                    error(\"Expected '{a}' and instead saw '{b}'.\",\n                            nexttoken, closetag(t.name), closetag(n));\n                }\n                if (nexttoken.id !== '>') {\n                    error(\"Missing '{a}'.\", nexttoken, '>');\n                }\n                xmode = 'outer';\n                advance('>');\n                break;\n            case '<!':\n                if (option.safe) {\n                    warning(\"ADsafe HTML violation.\");\n                }\n                xmode = 'html';\n                for (;;) {\n                    advance();\n                    if (nexttoken.id === '>' || nexttoken.id === '(end)') {\n                        break;\n                    }\n                    if (nexttoken.value.indexOf('--') >= 0) {\n                        error(\"Unexpected --.\");\n                    }\n                    if (nexttoken.value.indexOf('<') >= 0) {\n                        error(\"Unexpected <.\");\n                    }\n                    if (nexttoken.value.indexOf('>') >= 0) {\n                        error(\"Unexpected >.\");\n                    }\n                }\n                xmode = 'outer';\n                advance('>');\n                break;\n            case '(end)':\n                return;\n            default:\n                if (nexttoken.id === '(end)') {\n                    error(\"Missing '{a}'.\", nexttoken,\n                            '</' + stack[stack.length - 1].value + '>');\n                } else {\n                    advance();\n                }\n            }\n            if (stack && stack.length === 0 && (option.adsafe ||\n                    !option.fragment || nexttoken.id === '(end)')) {\n                break;\n            }\n        }\n        if (nexttoken.id !== '(end)') {\n            error(\"Unexpected material after the end.\");\n        }\n    }\n\n\n// Build the syntax table by declaring the syntactic elements of the language.\n\n    type('(number)', function () {\n        return this;\n    });\n    type('(string)', function () {\n        return this;\n    });\n\n    syntax['(identifier)'] = {\n        type: '(identifier)',\n        lbp: 0,\n        identifier: true,\n        nud: function () {\n            var v = this.value,\n                s = scope[v],\n                f;\n            if (typeof s === 'function') {\n\n// Protection against accidental inheritance.\n\n                s = undefined;\n            } else if (typeof s === 'boolean') {\n                f = funct;\n                funct = functions[0];\n                addlabel(v, 'var');\n                s = funct;\n                funct = f;\n            }\n\n// The name is in scope and defined in the current function.\n\n            if (funct === s) {\n\n//      Change 'unused' to 'var', and reject labels.\n\n                switch (funct[v]) {\n                case 'unused':\n                    funct[v] = 'var';\n                    break;\n                case 'unction':\n                    funct[v] = 'function';\n                    this['function'] = true;\n                    break;\n                case 'function':\n                    this['function'] = true;\n                    break;\n                case 'label':\n                    warning(\"'{a}' is a statement label.\", token, v);\n                    break;\n                }\n\n// The name is not defined in the function.  If we are in the global scope,\n// then we have an undefined variable.\n\n            } else if (funct['(global)']) {\n                if (option.undef && typeof predefined[v] !== 'boolean') {\n                    warning(\"'{a}' is not defined.\", token, v);\n                }\n                note_implied(token);\n\n// If the name is already defined in the current\n// function, but not as outer, then there is a scope error.\n\n            } else {\n                switch (funct[v]) {\n                case 'closure':\n                case 'function':\n                case 'var':\n                case 'unused':\n                    warning(\"'{a}' used out of scope.\", token, v);\n                    break;\n                case 'label':\n                    warning(\"'{a}' is a statement label.\", token, v);\n                    break;\n                case 'outer':\n                case 'global':\n                    break;\n                default:\n\n// If the name is defined in an outer function, make an outer entry, and if\n// it was unused, make it var.\n\n                    if (s === true) {\n                        funct[v] = true;\n                    } else if (s === null) {\n                        warning(\"'{a}' is not allowed.\", token, v);\n                        note_implied(token);\n                    } else if (typeof s !== 'object') {\n                        if (option.undef) {\n                            warning(\"'{a}' is not defined.\", token, v);\n                        } else {\n                            funct[v] = true;\n                        }\n                        note_implied(token);\n                    } else {\n                        switch (s[v]) {\n                        case 'function':\n                        case 'unction':\n                            this['function'] = true;\n                            s[v] = 'closure';\n                            funct[v] = s['(global)'] ? 'global' : 'outer';\n                            break;\n                        case 'var':\n                        case 'unused':\n                            s[v] = 'closure';\n                            funct[v] = s['(global)'] ? 'global' : 'outer';\n                            break;\n                        case 'closure':\n                        case 'parameter':\n                            funct[v] = s['(global)'] ? 'global' : 'outer';\n                            break;\n                        case 'label':\n                            warning(\"'{a}' is a statement label.\", token, v);\n                        }\n                    }\n                }\n            }\n            return this;\n        },\n        led: function () {\n            error(\"Expected an operator and instead saw '{a}'.\",\n                nexttoken, nexttoken.value);\n        }\n    };\n\n    type('(regexp)', function () {\n        return this;\n    });\n\n\n// ECMAScript parser\n\n    delim('(endline)');\n    delim('(begin)');\n    delim('(end)').reach = true;\n    delim('</').reach = true;\n    delim('<!');\n    delim('<!--');\n    delim('-->');\n    delim('(error)').reach = true;\n    delim('}').reach = true;\n    delim(')');\n    delim(']');\n    delim('\"').reach = true;\n    delim(\"'\").reach = true;\n    delim(';');\n    delim(':').reach = true;\n    delim(',');\n    delim('#');\n    delim('@');\n    reserve('else');\n    reserve('case').reach = true;\n    reserve('catch');\n    reserve('default').reach = true;\n    reserve('finally');\n    reservevar('arguments', function (x) {\n        if (strict_mode && funct['(global)']) {\n            warning(\"Strict violation.\", x);\n        } else if (option.safe) {\n            warning(\"ADsafe violation.\", x);\n        }\n    });\n    reservevar('eval', function (x) {\n        if (option.safe) {\n            warning(\"ADsafe violation.\", x);\n        }\n    });\n    reservevar('false');\n    reservevar('Infinity');\n    reservevar('NaN');\n    reservevar('null');\n    reservevar('this', function (x) {\n        if (strict_mode && ((funct['(statement)'] &&\n                funct['(name)'].charAt(0) > 'Z') || funct['(global)'])) {\n            warning(\"Strict violation.\", x);\n        } else if (option.safe) {\n            warning(\"ADsafe violation.\", x);\n        }\n    });\n    reservevar('true');\n    reservevar('undefined');\n    assignop('=', 'assign', 20);\n    assignop('+=', 'assignadd', 20);\n    assignop('-=', 'assignsub', 20);\n    assignop('*=', 'assignmult', 20);\n    assignop('/=', 'assigndiv', 20).nud = function () {\n        error(\"A regular expression literal can be confused with '/='.\");\n    };\n    assignop('%=', 'assignmod', 20);\n    bitwiseassignop('&=', 'assignbitand', 20);\n    bitwiseassignop('|=', 'assignbitor', 20);\n    bitwiseassignop('^=', 'assignbitxor', 20);\n    bitwiseassignop('<<=', 'assignshiftleft', 20);\n    bitwiseassignop('>>=', 'assignshiftright', 20);\n    bitwiseassignop('>>>=', 'assignshiftrightunsigned', 20);\n    infix('?', function (left, that) {\n        that.left = left;\n        that.right = expression(10);\n        advance(':');\n        that['else'] = expression(10);\n        return that;\n    }, 30);\n\n    infix('||', 'or', 40);\n    infix('&&', 'and', 50);\n    bitwise('|', 'bitor', 70);\n    bitwise('^', 'bitxor', 80);\n    bitwise('&', 'bitand', 90);\n    relation('==', function (left, right) {\n        if (option.eqeqeq) {\n            warning(\"Expected '{a}' and instead saw '{b}'.\",\n                    this, '===', '==');\n        } else if (isPoorRelation(left)) {\n            warning(\"Use '{a}' to compare with '{b}'.\",\n                this, '===', left.value);\n        } else if (isPoorRelation(right)) {\n            warning(\"Use '{a}' to compare with '{b}'.\",\n                this, '===', right.value);\n        }\n        return this;\n    });\n    relation('===');\n    relation('!=', function (left, right) {\n        if (option.eqeqeq) {\n            warning(\"Expected '{a}' and instead saw '{b}'.\",\n                    this, '!==', '!=');\n        } else if (isPoorRelation(left)) {\n            warning(\"Use '{a}' to compare with '{b}'.\",\n                    this, '!==', left.value);\n        } else if (isPoorRelation(right)) {\n            warning(\"Use '{a}' to compare with '{b}'.\",\n                    this, '!==', right.value);\n        }\n        return this;\n    });\n    relation('!==');\n    relation('<');\n    relation('>');\n    relation('<=');\n    relation('>=');\n    bitwise('<<', 'shiftleft', 120);\n    bitwise('>>', 'shiftright', 120);\n    bitwise('>>>', 'shiftrightunsigned', 120);\n    infix('in', 'in', 120);\n    infix('instanceof', 'instanceof', 120);\n    infix('+', function (left, that) {\n        var right = expression(130);\n        if (left && right && left.id === '(string)' && right.id === '(string)') {\n            left.value += right.value;\n            left.character = right.character;\n            if (jx.test(left.value)) {\n                warning(\"JavaScript URL.\", left);\n            }\n            return left;\n        }\n        that.left = left;\n        that.right = right;\n        return that;\n    }, 130);\n    prefix('+', 'num');\n    prefix('+++', function () {\n        warning(\"Confusing pluses.\");\n        this.right = expression(150);\n        this.arity = 'unary';\n        return this;\n    });\n    infix('+++', function (left) {\n        warning(\"Confusing pluses.\");\n        this.left = left;\n        this.right = expression(130);\n        return this;\n    }, 130);\n    infix('-', 'sub', 130);\n    prefix('-', 'neg');\n    prefix('---', function () {\n        warning(\"Confusing minuses.\");\n        this.right = expression(150);\n        this.arity = 'unary';\n        return this;\n    });\n    infix('---', function (left) {\n        warning(\"Confusing minuses.\");\n        this.left = left;\n        this.right = expression(130);\n        return this;\n    }, 130);\n    infix('*', 'mult', 140);\n    infix('/', 'div', 140);\n    infix('%', 'mod', 140);\n\n    suffix('++', 'postinc');\n    prefix('++', 'preinc');\n    syntax['++'].exps = true;\n\n    suffix('--', 'postdec');\n    prefix('--', 'predec');\n    syntax['--'].exps = true;\n    prefix('delete', function () {\n        var p = expression(0);\n        if (!p || (p.id !== '.' && p.id !== '[')) {\n            warning(\"Variables should not be deleted.\");\n        }\n        this.first = p;\n        return this;\n    }).exps = true;\n\n\n    prefix('~', function () {\n        if (option.bitwise) {\n            warning(\"Unexpected '{a}'.\", this, '~');\n        }\n        expression(150);\n        return this;\n    });\n    prefix('!', function () {\n        this.right = expression(150);\n        this.arity = 'unary';\n        if (bang[this.right.id] === true) {\n            warning(\"Confusing use of '{a}'.\", this, '!');\n        }\n        return this;\n    });\n    prefix('typeof', 'typeof');\n    prefix('new', function () {\n        var c = expression(155), i;\n        if (c && c.id !== 'function') {\n            if (c.identifier) {\n                c['new'] = true;\n                switch (c.value) {\n                case 'Object':\n                    warning(\"Use the object literal notation {}.\", token);\n                    break;\n                case 'Array':\n                    if (nexttoken.id !== '(') {\n                        warning(\"Use the array literal notation [].\", token);\n                    } else {\n                        advance('(');\n                        if (nexttoken.id === ')') {\n                            warning(\"Use the array literal notation [].\", token);\n                        }\n                        advance(')');\n                    }\n                    this.first = c;\n                    return this;\n                case 'Number':\n                case 'String':\n                case 'Boolean':\n                case 'Math':\n                case 'JSON':\n                    warning(\"Do not use {a} as a constructor.\", token, c.value);\n                    break;\n                case 'Function':\n                    if (!option.evil) {\n                        warning(\"The Function constructor is eval.\");\n                    }\n                    break;\n                case 'Date':\n                case 'RegExp':\n                    break;\n                default:\n                    if (c.id !== 'function') {\n                        i = c.value.substr(0, 1);\n                        if (option.newcap && (i < 'A' || i > 'Z')) {\n                            warning(\n                    \"A constructor name should start with an uppercase letter.\",\n                                token);\n                        }\n                    }\n                }\n            } else {\n                if (c.id !== '.' && c.id !== '[' && c.id !== '(') {\n                    warning(\"Bad constructor.\", token);\n                }\n            }\n        } else {\n            warning(\"Weird construction. Delete 'new'.\", this);\n        }\n        adjacent(token, nexttoken);\n        if (nexttoken.id !== '(') {\n            warning(\"Missing '()' invoking a constructor.\");\n        }\n        this.first = c;\n        return this;\n    });\n    syntax['new'].exps = true;\n\n    infix('.', function (left, that) {\n        adjacent(prevtoken, token);\n        nobreak();\n        var m = identifier();\n        if (typeof m === 'string') {\n            countMember(m);\n        }\n        that.left = left;\n        that.right = m;\n        if (option.noarg && left && left.value === 'arguments' &&\n                (m === 'callee' || m === 'caller')) {\n            warning(\"Avoid arguments.{a}.\", left, m);\n        } else if (!option.evil && left && left.value === 'document' &&\n                (m === 'write' || m === 'writeln')) {\n            warning(\"document.write can be a form of eval.\", left);\n        } else if (option.adsafe) {\n            if (left && left.value === 'ADSAFE') {\n                if (m === 'id' || m === 'lib') {\n                    warning(\"ADsafe violation.\", that);\n                } else if (m === 'go') {\n                    if (xmode !== 'script') {\n                        warning(\"ADsafe violation.\", that);\n                    } else if (adsafe_went || nexttoken.id !== '(' ||\n                            peek(0).id !== '(string)' ||\n                            peek(0).value !== adsafe_id ||\n                            peek(1).id !== ',') {\n                        error(\"ADsafe violation: go.\", that);\n                    }\n                    adsafe_went = true;\n                    adsafe_may = false;\n                }\n            }\n        }\n        if (!option.evil && (m === 'eval' || m === 'execScript')) {\n            warning('eval is evil.');\n        } else if (option.safe) {\n            for (;;) {\n                if (banned[m] === true) {\n                    warning(\"ADsafe restricted word '{a}'.\", token, m);\n                }\n                if (typeof predefined[left.value] !== 'boolean' ||\n                        nexttoken.id === '(') {\n                    break;\n                }\n                if (standard_member[m] === true) {\n                    if (nexttoken.id === '.') {\n                        warning(\"ADsafe violation.\", that);\n                    }\n                    break;\n                }\n                if (nexttoken.id !== '.') {\n                    warning(\"ADsafe violation.\", that);\n                    break;\n                }\n                advance('.');\n                token.left = that;\n                token.right = m;\n                that = token;\n                m = identifier();\n                if (typeof m === 'string') {\n                    countMember(m);\n                }\n            }\n        }\n        return that;\n    }, 160, true);\n\n    infix('(', function (left, that) {\n        if (prevtoken.id !== '}' && prevtoken.id !== ')') {\n            nobreak(prevtoken, token);\n        }\n        nospace();\n        if (option.immed && !left.immed && left.id === 'function') {\n            warning(\"Wrap an immediate function invocation in parentheses \" +\n                \"to assist the reader in understanding that the expression \" +\n                \"is the result of a function, and not the function itself.\");\n        }\n        var n = 0,\n            p = [];\n        if (left) {\n            if (left.type === '(identifier)') {\n                if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {\n                    if (left.value !== 'Number' && left.value !== 'String' &&\n                            left.value !== 'Boolean' &&\n                            left.value !== 'Date') {\n                        if (left.value === 'Math') {\n                            warning(\"Math is not a function.\", left);\n                        } else if (option.newcap) {\n                            warning(\n\"Missing 'new' prefix when invoking a constructor.\", left);\n                        }\n                    }\n                }\n            } else if (left.id === '.') {\n                if (option.safe && left.left.value === 'Math' &&\n                        left.right === 'random') {\n                    warning(\"ADsafe violation.\", left);\n                }\n            }\n        }\n        if (nexttoken.id !== ')') {\n            for (;;) {\n                p[p.length] = expression(10);\n                n += 1;\n                if (nexttoken.id !== ',') {\n                    break;\n                }\n                comma();\n            }\n        }\n        advance(')');\n        nospace(prevtoken, token);\n        if (typeof left === 'object') {\n            if (left.value === 'parseInt' && n === 1) {\n                warning(\"Missing radix parameter.\", left);\n            }\n            if (!option.evil) {\n                if (left.value === 'eval' || left.value === 'Function' ||\n                        left.value === 'execScript') {\n                    warning(\"eval is evil.\", left);\n                } else if (p[0] && p[0].id === '(string)' &&\n                       (left.value === 'setTimeout' ||\n                        left.value === 'setInterval')) {\n                    warning(\n    \"Implied eval is evil. Pass a function instead of a string.\", left);\n                }\n            }\n            if (!left.identifier && left.id !== '.' && left.id !== '[' &&\n                    left.id !== '(' && left.id !== '&&' && left.id !== '||' &&\n                    left.id !== '?') {\n                warning(\"Bad invocation.\", left);\n            }\n        }\n        that.left = left;\n        return that;\n    }, 155, true).exps = true;\n\n    prefix('(', function () {\n        nospace();\n        if (nexttoken.id === 'function') {\n            nexttoken.immed = true;\n        }\n        var v = expression(0);\n        advance(')', this);\n        nospace(prevtoken, token);\n        if (option.immed && v.id === 'function') {\n            if (nexttoken.id === '(') {\n                warning(\n\"Move the invocation into the parens that contain the function.\", nexttoken);\n            } else {\n                warning(\n\"Do not wrap function literals in parens unless they are to be immediately invoked.\",\n                        this);\n            }\n        }\n        return v;\n    });\n\n    infix('[', function (left, that) {\n        nobreak(prevtoken, token);\n        nospace();\n        var e = expression(0), s;\n        if (e && e.type === '(string)') {\n            if (option.safe && banned[e.value] === true) {\n                warning(\"ADsafe restricted word '{a}'.\", that, e.value);\n            } else if (!option.evil &&\n                    (e.value === 'eval' || e.value === 'execScript')) {\n                warning(\"eval is evil.\", that);\n            } else if (option.safe &&\n                    (e.value.charAt(0) === '_' || e.value.charAt(0) === '-')) {\n                warning(\"ADsafe restricted subscript '{a}'.\", that, e.value);\n            }\n            countMember(e.value);\n            if (!option.sub && ix.test(e.value)) {\n                s = syntax[e.value];\n                if (!s || !s.reserved) {\n                    warning(\"['{a}'] is better written in dot notation.\",\n                            e, e.value);\n                }\n            }\n        } else if (!e || e.type !== '(number)' || e.value < 0) {\n            if (option.safe) {\n                warning('ADsafe subscripting.');\n            }\n        }\n        advance(']', that);\n        nospace(prevtoken, token);\n        that.left = left;\n        that.right = e;\n        return that;\n    }, 160, true);\n\n    prefix('[', function () {\n        var b = token.line !== nexttoken.line;\n        this.first = [];\n        if (b) {\n            indent += option.indent;\n            if (nexttoken.from === indent + option.indent) {\n                indent += option.indent;\n            }\n        }\n        while (nexttoken.id !== '(end)') {\n            while (nexttoken.id === ',') {\n                warning(\"Extra comma.\");\n                advance(',');\n            }\n            if (nexttoken.id === ']') {\n                break;\n            }\n            if (b && token.line !== nexttoken.line) {\n                indentation();\n            }\n            this.first.push(expression(10));\n            if (nexttoken.id === ',') {\n                comma();\n                if (nexttoken.id === ']' && !option.es5) {\n                    warning(\"Extra comma.\", token);\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n        if (b) {\n            indent -= option.indent;\n            indentation();\n        }\n        advance(']', this);\n        return this;\n    }, 160);\n\n\n    function property_name() {\n        var id = optionalidentifier(true);\n        if (!id) {\n            if (nexttoken.id === '(string)') {\n                id = nexttoken.value;\n                if (option.adsafe &&\n                        (id.charAt(0) === '_' ||\n                         id.charAt(id.length - 1) === '_')) {\n                    warning(\"Unexpected {a} in '{b}'.\", token,\n                        \"dangling '_'\", id);\n                }\n                advance();\n            } else if (nexttoken.id === '(number)') {\n                id = nexttoken.value.toString();\n                advance();\n            }\n        }\n        return id;\n    }\n\n\n    function functionparams() {\n        var i, t = nexttoken, p = [];\n        advance('(');\n        nospace();\n        if (nexttoken.id === ')') {\n            advance(')');\n            nospace(prevtoken, token);\n            return;\n        }\n        for (;;) {\n            i = identifier();\n            p.push(i);\n            addlabel(i, 'parameter');\n            if (nexttoken.id === ',') {\n                comma();\n            } else {\n                advance(')', t);\n                nospace(prevtoken, token);\n                return p;\n            }\n        }\n    }\n\n\n    function doFunction(i, statement) {\n        var f, s = scope;\n        scope = Object.create(s);\n        funct = {\n            '(name)'     : i || '\"' + anonname + '\"',\n            '(line)'     : nexttoken.line,\n            '(context)'  : funct,\n            '(breakage)' : 0,\n            '(loopage)'  : 0,\n            '(scope)'    : scope,\n            '(statement)': statement\n        };\n        f = funct;\n        token.funct = funct;\n        functions.push(funct);\n        if (i) {\n            addlabel(i, 'function');\n        }\n        funct['(params)'] = functionparams();\n\n        block(false);\n        scope = s;\n        funct['(last)'] = token.line;\n        funct = funct['(context)'];\n        return f;\n    }\n\n\n    (function (x) {\n        x.nud = function () {\n            var b, f, i, j, p, seen = {}, t;\n            b = token.line !== nexttoken.line;\n            if (b) {\n                indent += option.indent;\n                if (nexttoken.from === indent + option.indent) {\n                    indent += option.indent;\n                }\n            }\n            for (;;) {\n                if (nexttoken.id === '}') {\n                    break;\n                }\n                if (b) {\n                    indentation();\n                }\n                if (nexttoken.value === 'get' && peek().id !== ':') {\n                    advance('get');\n                    if (!option.es5) {\n                        error(\"get/set are ES5 features.\");\n                    }\n                    i = property_name();\n                    if (!i) {\n                        error(\"Missing property name.\");\n                    }\n                    t = nexttoken;\n                    adjacent(token, nexttoken);\n                    f = doFunction(i);\n                    if (funct['(loopage)']) {\n                        warning(\"Don't make functions within a loop.\", t);\n                    }\n                    p = f['(params)'];\n                    if (p) {\n                        warning(\"Unexpected parameter '{a}' in get {b} function.\", t, p[0], i);\n                    }\n                    adjacent(token, nexttoken);\n                    advance(',');\n                    indentation();\n                    advance('set');\n                    j = property_name();\n                    if (i !== j) {\n                        error(\"Expected {a} and instead saw {b}.\", token, i, j);\n                    }\n                    t = nexttoken;\n                    adjacent(token, nexttoken);\n                    f = doFunction(i);\n                    p = f['(params)'];\n                    if (!p || p.length !== 1 || p[0] !== 'value') {\n                        warning(\"Expected (value) in set {a} function.\", t, i);\n                    }\n                } else {\n                    i = property_name();\n                    if (typeof i !== 'string') {\n                        break;\n                    }\n                    advance(':');\n                    nonadjacent(token, nexttoken);\n                    expression(10);\n                }\n                if (seen[i] === true) {\n                    warning(\"Duplicate member '{a}'.\", nexttoken, i);\n                }\n                seen[i] = true;\n                countMember(i);\n                if (nexttoken.id === ',') {\n                    comma();\n                    if (nexttoken.id === ',') {\n                        warning(\"Extra comma.\", token);\n                    } else if (nexttoken.id === '}' && !option.es5) {\n                        warning(\"Extra comma.\", token);\n                    }\n                } else {\n                    break;\n                }\n            }\n            if (b) {\n                indent -= option.indent;\n                indentation();\n            }\n            advance('}', this);\n            return this;\n        };\n        x.fud = function () {\n            error(\"Expected to see a statement and instead saw a block.\", token);\n        };\n    }(delim('{')));\n\n\n    var varstatement = function varstatement(prefix) {\n\n// JavaScript does not have block scope. It only has function scope. So,\n// declaring a variable in a block can have unexpected consequences.\n\n        var id, name, value;\n\n        if (funct['(onevar)'] && option.onevar) {\n            warning(\"Too many var statements.\");\n        } else if (!funct['(global)']) {\n            funct['(onevar)'] = true;\n        }\n        this.first = [];\n        for (;;) {\n            nonadjacent(token, nexttoken);\n            id = identifier();\n            if (funct['(global)'] && predefined[id] === false) {\n                warning(\"Redefinition of '{a}'.\", token, id);\n            }\n            addlabel(id, 'unused');\n            if (prefix) {\n                break;\n            }\n            name = token;\n            this.first.push(token);\n            if (nexttoken.id === '=') {\n                nonadjacent(token, nexttoken);\n                advance('=');\n                nonadjacent(token, nexttoken);\n                if (nexttoken.id === 'undefined') {\n                    warning(\"It is not necessary to initialize '{a}' to 'undefined'.\", token, id);\n                }\n                if (peek(0).id === '=' && nexttoken.identifier) {\n                    error(\"Variable {a} was not declared correctly.\",\n                            nexttoken, nexttoken.value);\n                }\n                value = expression(0);\n                name.first = value;\n            }\n            if (nexttoken.id !== ',') {\n                break;\n            }\n            comma();\n        }\n        return this;\n    };\n\n\n    stmt('var', varstatement).exps = true;\n\n\n    blockstmt('function', function () {\n        if (inblock) {\n            warning(\n\"Function statements should not be placed in blocks. Use a function expression or move the statement to the top of the outer function.\", token);\n\n        }\n        var i = identifier();\n        adjacent(token, nexttoken);\n        addlabel(i, 'unction');\n        doFunction(i, true);\n        if (nexttoken.id === '(' && nexttoken.line === token.line) {\n            error(\n\"Function statements are not invocable. Wrap the whole function invocation in parens.\");\n        }\n        return this;\n    });\n\n    prefix('function', function () {\n        var i = optionalidentifier();\n        if (i) {\n            adjacent(token, nexttoken);\n        } else {\n            nonadjacent(token, nexttoken);\n        }\n        doFunction(i);\n        if (funct['(loopage)']) {\n            warning(\"Don't make functions within a loop.\");\n        }\n        return this;\n    });\n\n    blockstmt('if', function () {\n        var t = nexttoken;\n        advance('(');\n        nonadjacent(this, t);\n        nospace();\n        expression(20);\n        if (nexttoken.id === '=') {\n            if (!option.boss)\n                warning(\"Expected a conditional expression and instead saw an assignment.\");\n            advance('=');\n            expression(20);\n        }\n        advance(')', t);\n        nospace(prevtoken, token);\n        block(true, true);\n        if (nexttoken.id === 'else') {\n            nonadjacent(token, nexttoken);\n            advance('else');\n            if (nexttoken.id === 'if' || nexttoken.id === 'switch') {\n                statement(true);\n            } else {\n                block(true, true);\n            }\n        }\n        return this;\n    });\n\n    blockstmt('try', function () {\n        var b, e, s;\n        if (option.adsafe) {\n            warning(\"ADsafe try violation.\", this);\n        }\n        block(false);\n        if (nexttoken.id === 'catch') {\n            advance('catch');\n            nonadjacent(token, nexttoken);\n            advance('(');\n            s = scope;\n            scope = Object.create(s);\n            e = nexttoken.value;\n            if (nexttoken.type !== '(identifier)') {\n                warning(\"Expected an identifier and instead saw '{a}'.\",\n                    nexttoken, e);\n            } else {\n                addlabel(e, 'exception');\n            }\n            advance();\n            advance(')');\n            block(false);\n            b = true;\n            scope = s;\n        }\n        if (nexttoken.id === 'finally') {\n            advance('finally');\n            block(false);\n            return;\n        } else if (!b) {\n            error(\"Expected '{a}' and instead saw '{b}'.\",\n                    nexttoken, 'catch', nexttoken.value);\n        }\n        return this;\n    });\n\n    blockstmt('while', function () {\n        var t = nexttoken;\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        advance('(');\n        nonadjacent(this, t);\n        nospace();\n        expression(20);\n        if (nexttoken.id === '=') {\n            if (!option.boss)\n                warning(\"Expected a conditional expression and instead saw an assignment.\");\n            advance('=');\n            expression(20);\n        }\n        advance(')', t);\n        nospace(prevtoken, token);\n        block(true, true);\n        funct['(breakage)'] -= 1;\n        funct['(loopage)'] -= 1;\n        return this;\n    }).labelled = true;\n\n    reserve('with');\n\n    blockstmt('switch', function () {\n        var t = nexttoken,\n            g = false;\n        funct['(breakage)'] += 1;\n        advance('(');\n        nonadjacent(this, t);\n        nospace();\n        this.condition = expression(20);\n        advance(')', t);\n        nospace(prevtoken, token);\n        nonadjacent(token, nexttoken);\n        t = nexttoken;\n        advance('{');\n        nonadjacent(token, nexttoken);\n        indent += option.indent;\n        this.cases = [];\n        for (;;) {\n            switch (nexttoken.id) {\n            case 'case':\n                switch (funct['(verb)']) {\n                case 'break':\n                case 'case':\n                case 'continue':\n                case 'return':\n                case 'switch':\n                case 'throw':\n                    break;\n                default:\n                    warning(\n                        \"Expected a 'break' statement before 'case'.\",\n                        token);\n                }\n                indentation(-option.indent);\n                advance('case');\n                this.cases.push(expression(20));\n                g = true;\n                advance(':');\n                funct['(verb)'] = 'case';\n                break;\n            case 'default':\n                switch (funct['(verb)']) {\n                case 'break':\n                case 'continue':\n                case 'return':\n                case 'throw':\n                    break;\n                default:\n                    warning(\n                        \"Expected a 'break' statement before 'default'.\",\n                        token);\n                }\n                indentation(-option.indent);\n                advance('default');\n                g = true;\n                advance(':');\n                break;\n            case '}':\n                indent -= option.indent;\n                indentation();\n                advance('}', t);\n                if (this.cases.length === 1 || this.condition.id === 'true' ||\n                        this.condition.id === 'false') {\n                    warning(\"This 'switch' should be an 'if'.\", this);\n                }\n                funct['(breakage)'] -= 1;\n                funct['(verb)'] = undefined;\n                return;\n            case '(end)':\n                error(\"Missing '{a}'.\", nexttoken, '}');\n                return;\n            default:\n                if (g) {\n                    switch (token.id) {\n                    case ',':\n                        error(\"Each value should have its own case label.\");\n                        return;\n                    case ':':\n                        statements();\n                        break;\n                    default:\n                        error(\"Missing ':' on a case clause.\", token);\n                    }\n                } else {\n                    error(\"Expected '{a}' and instead saw '{b}'.\",\n                        nexttoken, 'case', nexttoken.value);\n                }\n            }\n        }\n    }).labelled = true;\n\n    stmt('debugger', function () {\n        if (!option.debug) {\n            warning(\"All 'debugger' statements should be removed.\");\n        }\n        return this;\n    }).exps = true;\n\n    (function () {\n        var x = stmt('do', function () {\n            funct['(breakage)'] += 1;\n            funct['(loopage)'] += 1;\n            this.first = block(true);\n            advance('while');\n            var t = nexttoken;\n            nonadjacent(token, t);\n            advance('(');\n            nospace();\n            expression(20);\n            if (nexttoken.id === '=') {\n                if (!option.boss)\n                    warning(\"Expected a conditional expression and instead saw an assignment.\");\n                advance('=');\n                expression(20);\n            }\n            advance(')', t);\n            nospace(prevtoken, token);\n            funct['(breakage)'] -= 1;\n            funct['(loopage)'] -= 1;\n            return this;\n        });\n        x.labelled = true;\n        x.exps = true;\n    }());\n\n    blockstmt('for', function () {\n        var f = option.forin, s, t = nexttoken;\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        advance('(');\n        nonadjacent(this, t);\n        nospace();\n        if (peek(nexttoken.id === 'var' ? 1 : 0).id === 'in') {\n            if (nexttoken.id === 'var') {\n                advance('var');\n                varstatement(true);\n            } else {\n                switch (funct[nexttoken.value]) {\n                case 'unused':\n                    funct[nexttoken.value] = 'var';\n                    break;\n                case 'var':\n                    break;\n                default:\n                    warning(\"Bad for in variable '{a}'.\",\n                            nexttoken, nexttoken.value);\n                }\n                advance();\n            }\n            advance('in');\n            expression(20);\n            advance(')', t);\n            s = block(true, true);\n            if (!f && (s.length > 1 || typeof s[0] !== 'object' ||\n                    s[0].value !== 'if')) {\n                warning(\"The body of a for in should be wrapped in an if statement to filter unwanted properties from the prototype.\", this);\n            }\n            funct['(breakage)'] -= 1;\n            funct['(loopage)'] -= 1;\n            return this;\n        } else {\n            if (nexttoken.id !== ';') {\n                if (nexttoken.id === 'var') {\n                    advance('var');\n                    varstatement();\n                } else {\n                    for (;;) {\n                        expression(0, 'for');\n                        if (nexttoken.id !== ',') {\n                            break;\n                        }\n                        comma();\n                    }\n                }\n            }\n            nolinebreak(token);\n            advance(';');\n            if (nexttoken.id !== ';') {\n                expression(20);\n                if (nexttoken.id === '=') {\n                    if (!option.boss)\n                        warning(\"Expected a conditional expression and instead saw an assignment.\");\n                    advance('=');\n                    expression(20);\n                }\n            }\n            nolinebreak(token);\n            advance(';');\n            if (nexttoken.id === ';') {\n                error(\"Expected '{a}' and instead saw '{b}'.\",\n                        nexttoken, ')', ';');\n            }\n            if (nexttoken.id !== ')') {\n                for (;;) {\n                    expression(0, 'for');\n                    if (nexttoken.id !== ',') {\n                        break;\n                    }\n                    comma();\n                }\n            }\n            advance(')', t);\n            nospace(prevtoken, token);\n            block(true, true);\n            funct['(breakage)'] -= 1;\n            funct['(loopage)'] -= 1;\n            return this;\n        }\n    }).labelled = true;\n\n\n    stmt('break', function () {\n        var v = nexttoken.value;\n        if (funct['(breakage)'] === 0) {\n            warning(\"Unexpected '{a}'.\", nexttoken, this.value);\n        }\n        nolinebreak(this);\n        if (nexttoken.id !== ';') {\n            if (token.line === nexttoken.line) {\n                if (funct[v] !== 'label') {\n                    warning(\"'{a}' is not a statement label.\", nexttoken, v);\n                } else if (scope[v] !== funct) {\n                    warning(\"'{a}' is out of scope.\", nexttoken, v);\n                }\n                this.first = nexttoken;\n                advance();\n            }\n        }\n        reachable('break');\n        return this;\n    }).exps = true;\n\n\n    stmt('continue', function () {\n        var v = nexttoken.value;\n        if (funct['(breakage)'] === 0) {\n            warning(\"Unexpected '{a}'.\", nexttoken, this.value);\n        }\n        nolinebreak(this);\n        if (nexttoken.id !== ';') {\n            if (token.line === nexttoken.line) {\n                if (funct[v] !== 'label') {\n                    warning(\"'{a}' is not a statement label.\", nexttoken, v);\n                } else if (scope[v] !== funct) {\n                    warning(\"'{a}' is out of scope.\", nexttoken, v);\n                }\n                this.first = nexttoken;\n                advance();\n            }\n        } else if (!funct['(loopage)']) {\n            warning(\"Unexpected '{a}'.\", nexttoken, this.value);\n        }\n        reachable('continue');\n        return this;\n    }).exps = true;\n\n\n    stmt('return', function () {\n        nolinebreak(this);\n        if (nexttoken.id === '(regexp)') {\n            warning(\"Wrap the /regexp/ literal in parens to disambiguate the slash operator.\");\n        }\n        if (nexttoken.id !== ';' && !nexttoken.reach) {\n            nonadjacent(token, nexttoken);\n            this.first = expression(20);\n        }\n        reachable('return');\n        return this;\n    }).exps = true;\n\n\n    stmt('throw', function () {\n        nolinebreak(this);\n        nonadjacent(token, nexttoken);\n        this.first = expression(20);\n        reachable('throw');\n        return this;\n    }).exps = true;\n\n    reserve('void');\n\n//  Superfluous reserved words\n\n    reserve('class');\n    reserve('const');\n    reserve('enum');\n    reserve('export');\n    reserve('extends');\n    reserve('import');\n    reserve('super');\n\n    reserve('let');\n    reserve('yield');\n    reserve('implements');\n    reserve('interface');\n    reserve('package');\n    reserve('private');\n    reserve('protected');\n    reserve('public');\n    reserve('static');\n\n\n// Parse JSON\n\n    function jsonValue() {\n\n        function jsonObject() {\n            var o = {}, t = nexttoken;\n            advance('{');\n            if (nexttoken.id !== '}') {\n                for (;;) {\n                    if (nexttoken.id === '(end)') {\n                        error(\"Missing '}' to match '{' from line {a}.\",\n                                nexttoken, t.line);\n                    } else if (nexttoken.id === '}') {\n                        warning(\"Unexpected comma.\", token);\n                        break;\n                    } else if (nexttoken.id === ',') {\n                        error(\"Unexpected comma.\", nexttoken);\n                    } else if (nexttoken.id !== '(string)') {\n                        warning(\"Expected a string and instead saw {a}.\",\n                                nexttoken, nexttoken.value);\n                    }\n                    if (o[nexttoken.value] === true) {\n                        warning(\"Duplicate key '{a}'.\",\n                                nexttoken, nexttoken.value);\n                    } else if (nexttoken.value === '__proto__') {\n                        warning(\"Stupid key '{a}'.\",\n                                nexttoken, nexttoken.value);\n                    } else {\n                        o[nexttoken.value] = true;\n                    }\n                    advance();\n                    advance(':');\n                    jsonValue();\n                    if (nexttoken.id !== ',') {\n                        break;\n                    }\n                    advance(',');\n                }\n            }\n            advance('}');\n        }\n\n        function jsonArray() {\n            var t = nexttoken;\n            advance('[');\n            if (nexttoken.id !== ']') {\n                for (;;) {\n                    if (nexttoken.id === '(end)') {\n                        error(\"Missing ']' to match '[' from line {a}.\",\n                                nexttoken, t.line);\n                    } else if (nexttoken.id === ']') {\n                        warning(\"Unexpected comma.\", token);\n                        break;\n                    } else if (nexttoken.id === ',') {\n                        error(\"Unexpected comma.\", nexttoken);\n                    }\n                    jsonValue();\n                    if (nexttoken.id !== ',') {\n                        break;\n                    }\n                    advance(',');\n                }\n            }\n            advance(']');\n        }\n\n        switch (nexttoken.id) {\n        case '{':\n            jsonObject();\n            break;\n        case '[':\n            jsonArray();\n            break;\n        case 'true':\n        case 'false':\n        case 'null':\n        case '(number)':\n        case '(string)':\n            advance();\n            break;\n        case '-':\n            advance('-');\n            if (token.character !== nexttoken.from) {\n                warning(\"Unexpected space after '-'.\", token);\n            }\n            adjacent(token, nexttoken);\n            advance('(number)');\n            break;\n        default:\n            error(\"Expected a JSON value.\", nexttoken);\n        }\n    }\n\n\n// The actual JSHINT function itself.\n\n    var itself = function (s, o) {\n        var a, i, k;\n        JSHINT.errors = [];\n        predefined = Object.create(standard);\n        if (o) {\n            a = o.predef;\n            if (a) {\n                if (Array.isArray(a)) {\n                    for (i = 0; i < a.length; i += 1) {\n                        predefined[a[i]] = true;\n                    }\n                } else if (typeof a === 'object') {\n                    k = Object.keys(a);\n                    for (i = 0; i < k.length; i += 1) {\n                        predefined[k[i]] = !!a[k];\n                    }\n                }\n            }\n            if (o.adsafe) {\n                o.safe = true;\n            }\n            if (o.safe) {\n                o.browser =\n                o.css     =\n                o.debug   =\n                o.devel   =\n                o.evil    =\n                o.forin   =\n                o.on      =\n                o.rhino   =\n                o.windows =\n                o.sub     =\n                o.widget  = false;\n\n                o.eqeqeq  =\n                o.nomen   =\n                o.safe    =\n                o.undef   = true;\n\n                predefined.Date =\n                predefined['eval'] =\n                predefined.Function =\n                predefined.Object = null;\n\n                predefined.ADSAFE =\n                predefined.lib = false;\n            }\n            option = o;\n        } else {\n            option = {};\n        }\n        option.indent = option.indent || 4;\n        option.maxerr = option.maxerr || 50;\n        adsafe_id = '';\n        adsafe_may = false;\n        adsafe_went = false;\n        approved = {};\n        if (option.approved) {\n            for (i = 0; i < option.approved.length; i += 1) {\n                approved[option.approved[i]] = option.approved[i];\n            }\n        } else {\n            approved.test = 'test';\n        }\n        tab = '';\n        for (i = 0; i < option.indent; i += 1) {\n            tab += ' ';\n        }\n        indent = 1;\n        global = Object.create(predefined);\n        scope = global;\n        funct = {\n            '(global)': true,\n            '(name)': '(global)',\n            '(scope)': scope,\n            '(breakage)': 0,\n            '(loopage)': 0\n        };\n        functions = [funct];\n        ids = {};\n        urls = [];\n        src = false;\n        xmode = false;\n        stack = null;\n        member = {};\n        membersOnly = null;\n        implied = {};\n        inblock = false;\n        lookahead = [];\n        jsonmode = false;\n        warnings = 0;\n        lex.init(s);\n        prereg = true;\n        strict_mode = false;\n\n        prevtoken = token = nexttoken = syntax['(begin)'];\n        assume();\n\n        try {\n            advance();\n            if (nexttoken.value.charAt(0) === '<') {\n                html();\n                if (option.adsafe && !adsafe_went) {\n                    warning(\"ADsafe violation: Missing ADSAFE.go.\", this);\n                }\n            } else {\n                switch (nexttoken.id) {\n                case '{':\n                case '[':\n                    option.laxbreak = true;\n                    jsonmode = true;\n                    jsonValue();\n                    break;\n                case '@':\n                case '*':\n                case '#':\n                case '.':\n                case ':':\n                    xmode = 'style';\n                    advance();\n                    if (token.id !== '@' || !nexttoken.identifier ||\n                            nexttoken.value !== 'charset' || token.line !== 1 ||\n                            token.from !== 1) {\n                        error(\"A css file should begin with @charset 'UTF-8';\");\n                    }\n                    advance();\n                    if (nexttoken.type !== '(string)' &&\n                            nexttoken.value !== 'UTF-8') {\n                        error(\"A css file should begin with @charset 'UTF-8';\");\n                    }\n                    advance();\n                    advance(';');\n                    styles();\n                    break;\n\n                default:\n                    if (option.adsafe && option.fragment) {\n                        error(\"Expected '{a}' and instead saw '{b}'.\",\n                            nexttoken, '<div>', nexttoken.value);\n                    }\n                    if (nexttoken.value === 'use strict') {\n                        warning(\"Use the function form of \\\"use strict\\\".\");\n                        use_strict();\n                    }\n                    statements('lib');\n                }\n            }\n            advance('(end)');\n        } catch (e) {\n            if (e) {\n                JSHINT.errors.push({\n                    reason    : e.message,\n                    line      : e.line || nexttoken.line,\n                    character : e.character || nexttoken.from\n                }, null);\n            }\n        }\n        return JSHINT.errors.length === 0;\n    };\n\n\n// Data summary.\n\n    itself.data = function () {\n\n        var data = {functions: []}, fu, globals, implieds = [], f, i, j,\n            members = [], n, unused = [], v;\n        if (itself.errors.length) {\n            data.errors = itself.errors;\n        }\n\n        if (jsonmode) {\n            data.json = true;\n        }\n\n        for (n in implied) {\n            if (is_own(implied, n)) {\n                implieds.push({\n                    name: n,\n                    line: implied[n]\n                });\n            }\n        }\n        if (implieds.length > 0) {\n            data.implieds = implieds;\n        }\n\n        if (urls.length > 0) {\n            data.urls = urls;\n        }\n\n        globals = Object.keys(scope);\n        if (globals.length > 0) {\n            data.globals = globals;\n        }\n\n        for (i = 1; i < functions.length; i += 1) {\n            f = functions[i];\n            fu = {};\n            for (j = 0; j < functionicity.length; j += 1) {\n                fu[functionicity[j]] = [];\n            }\n            for (n in f) {\n                if (is_own(f, n) && n.charAt(0) !== '(') {\n                    v = f[n];\n                    if (v === 'unction') {\n                        v = 'unused';\n                    }\n                    if (Array.isArray(fu[v])) {\n                        fu[v].push(n);\n                        if (v === 'unused') {\n                            unused.push({\n                                name: n,\n                                line: f['(line)'],\n                                'function': f['(name)']\n                            });\n                        }\n                    }\n                }\n            }\n            for (j = 0; j < functionicity.length; j += 1) {\n                if (fu[functionicity[j]].length === 0) {\n                    delete fu[functionicity[j]];\n                }\n            }\n            fu.name = f['(name)'];\n            fu.param = f['(params)'];\n            fu.line = f['(line)'];\n            fu.last = f['(last)'];\n            data.functions.push(fu);\n        }\n\n        if (unused.length > 0) {\n            data.unused = unused;\n        }\n\n        members = [];\n        for (n in member) {\n            if (typeof member[n] === 'number') {\n                data.member = member;\n                break;\n            }\n        }\n\n        return data;\n    };\n\n    itself.report = function (option) {\n        var data = itself.data();\n\n        var a = [], c, e, err, f, i, k, l, m = '', n, o = [], s;\n\n        function detail(h, array) {\n            var b, i, singularity;\n            if (array) {\n                o.push('<div><i>' + h + '</i> ');\n                array = array.sort();\n                for (i = 0; i < array.length; i += 1) {\n                    if (array[i] !== singularity) {\n                        singularity = array[i];\n                        o.push((b ? ', ' : '') + singularity);\n                        b = true;\n                    }\n                }\n                o.push('</div>');\n            }\n        }\n\n\n        if (data.errors || data.implieds || data.unused) {\n            err = true;\n            o.push('<div id=errors><i>Error:</i>');\n            if (data.errors) {\n                for (i = 0; i < data.errors.length; i += 1) {\n                    c = data.errors[i];\n                    if (c) {\n                        e = c.evidence || '';\n                        o.push('<p>Problem' + (isFinite(c.line) ? ' at line ' +\n                                c.line + ' character ' + c.character : '') +\n                                ': ' + c.reason.entityify() +\n                                '</p><p class=evidence>' +\n                                (e && (e.length > 80 ? e.slice(0, 77) + '...' :\n                                e).entityify()) + '</p>');\n                    }\n                }\n            }\n\n            if (data.implieds) {\n                s = [];\n                for (i = 0; i < data.implieds.length; i += 1) {\n                    s[i] = '<code>' + data.implieds[i].name + '</code>&nbsp;<i>' +\n                        data.implieds[i].line + '</i>';\n                }\n                o.push('<p><i>Implied global:</i> ' + s.join(', ') + '</p>');\n            }\n\n            if (data.unused) {\n                s = [];\n                for (i = 0; i < data.unused.length; i += 1) {\n                    s[i] = '<code><u>' + data.unused[i].name + '</u></code>&nbsp;<i>' +\n                        data.unused[i].line + '</i> <code>' +\n                        data.unused[i]['function'] + '</code>';\n                }\n                o.push('<p><i>Unused variable:</i> ' + s.join(', ') + '</p>');\n            }\n            if (data.json) {\n                o.push('<p>JSON: bad.</p>');\n            }\n            o.push('</div>');\n        }\n\n        if (!option) {\n\n            o.push('<br><div id=functions>');\n\n            if (data.urls) {\n                detail(\"URLs<br>\", data.urls, '<br>');\n            }\n\n            if (xmode === 'style') {\n                o.push('<p>CSS.</p>');\n            } else if (data.json && !err) {\n                o.push('<p>JSON: good.</p>');\n            } else if (data.globals) {\n                o.push('<div><i>Global</i> ' +\n                        data.globals.sort().join(', ') + '</div>');\n            } else {\n                o.push('<div><i>No new global variables introduced.</i></div>');\n            }\n\n            for (i = 0; i < data.functions.length; i += 1) {\n                f = data.functions[i];\n\n                o.push('<br><div class=function><i>' + f.line + '-' +\n                        f.last + '</i> ' + (f.name || '') + '(' +\n                        (f.param ? f.param.join(', ') : '') + ')</div>');\n                detail('<big><b>Unused</b></big>', f.unused);\n                detail('Closure', f.closure);\n                detail('Variable', f['var']);\n                detail('Exception', f.exception);\n                detail('Outer', f.outer);\n                detail('Global', f.global);\n                detail('Label', f.label);\n            }\n\n            if (data.member) {\n                a = Object.keys(data.member);\n                if (a.length) {\n                    a = a.sort();\n                    m = '<br><pre id=members>/*members ';\n                    l = 10;\n                    for (i = 0; i < a.length; i += 1) {\n                        k = a[i];\n                        n = k.name();\n                        if (l + n.length > 72) {\n                            o.push(m + '<br>');\n                            m = '    ';\n                            l = 1;\n                        }\n                        l += n.length + 2;\n                        if (data.member[k] === 1) {\n                            n = '<i>' + n + '</i>';\n                        }\n                        if (i < a.length - 1) {\n                            n += ', ';\n                        }\n                        m += n;\n                    }\n                    o.push(m + '<br>*/</pre>');\n                }\n                o.push('</div>');\n            }\n        }\n        return o.join('');\n    };\n    itself.jshint = itself;\n\n    return itself;\n\n}());\n\n// Make JSHINT a Node module, if possible.\nif (typeof exports == 'object' && exports)\n    exports.JSHINT = JSHINT;\n    \n\n// Command line integration via Rhino\n(function (args) {\n    var name = args[0],\n        optstr = args[1], // arg1=val1,arg2=val2,...\n        opts = { rhino: true },\n        input;\n\n    if (!name) {\n        print('No files present in the fileset; Check your pattern match in build.xml');\n        quit(1);\n    }\n\n    if (optstr) {\n        optstr.split(',').forEach(function (arg) {\n            var o = arg.split('=');\n            opts[o[0]] = (function (ov) {\n                switch (ov) {\n                case 'true':\n                    return true;\n                case 'false':\n                    return false;\n                default:\n                    return ov;\n                }\n            })(o[1]);\n        });\n    }\n\n    input = readFile(name);\n\n    if (!input) {\n        print('JSHint: Couldn\\'t open file ' + name);\n        quit(1);\n    }\n    if (!JSHINT(input, opts)) {\n        for (var i = 0, err; err = JSHINT.errors[i]; i++) {\n            print(err.reason + ' (line: ' + err.line + ', character: ' + err.character + ')');\n            print('> ' + (err.evidence || '').replace(/^\\s*(\\S*(\\s+\\S+)*)\\s*$/, \"$1\"));\n            print('');\n        }\n        quit(1);\n    }\n\n    quit(0);\n}(arguments));\n\n\n\n\n"
  },
  {
    "path": "build/tools/fulljslint.js",
    "content": "/*global quit:false, readFile: false */\n\n// Rhino Edition\n\n\n// jslint.js\n// 2011-03-29\n\n// Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)\n\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n\n// The Software shall be used for Good, not Evil.\n\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n\n// JSLINT is a global function. It takes two parameters.\n\n//     var myResult = JSLINT(source, option);\n\n// The first parameter is either a string or an array of strings. If it is a\n// string, it will be split on '\\n' or '\\r'. If it is an array of strings, it\n// is assumed that each string represents one line. The source can be a\n// JavaScript text, or HTML text, or a JSON text, or a CSS text.\n\n// The second parameter is an optional object of options that control the\n// operation of JSLINT. Most of the options are booleans: They are all\n// optional and have a default value of false. One of the options, predef,\n// can be an array of names, which will be used to declare global variables,\n// or an object whose keys are used as global names, with a boolean value\n// that determines if they are assignable.\n\n// If it checks out, JSLINT returns true. Otherwise, it returns false.\n\n// If false, you can inspect JSLINT.errors to find out the problems.\n// JSLINT.errors is an array of objects containing these properties:\n\n//  {\n//      line      : The line (relative to 0) at which the lint was found\n//      character : The character (relative to 0) at which the lint was found\n//      reason    : The problem\n//      evidence  : The text line in which the problem occurred\n//      raw       : The raw message before the details were inserted\n//      a         : The first detail\n//      b         : The second detail\n//      c         : The third detail\n//      d         : The fourth detail\n//  }\n\n// If a stopping error was found, a null will be the last element of the\n// JSLINT.errors array. A stopping error means that JSLint was not confident\n// enough to continue. It does not necessarily mean that the error was\n// especailly heinous.\n\n// You can request a Function Report, which shows all of the functions\n// and the parameters and vars that they use. This can be used to find\n// implied global variables and other problems. The report is in HTML and\n// can be inserted in an HTML <body>.\n\n//     var myReport = JSLINT.report(errors_only);\n\n// If errors_only is true, then the report will be limited to only errors.\n\n// You can request a data structure that contains JSLint's results.\n\n//     var myData = JSLINT.data();\n\n// It returns a structure with this form:\n\n//     {\n//         errors: [\n//             {\n//                 line: NUMBER,\n//                 character: NUMBER,\n//                 reason: STRING,\n//                 evidence: STRING\n//             }\n//         ],\n//         functions: [\n//             name: STRING,\n//             line: NUMBER,\n//             last: NUMBER,\n//             param: [\n//                 TOKEN\n//             ],\n//             closure: [\n//                 STRING\n//             ],\n//             var: [\n//                 STRING\n//             ],\n//             exception: [\n//                 STRING\n//             ],\n//             outer: [\n//                 STRING\n//             ],\n//             unused: [\n//                 STRING\n//             ],\n//             global: [\n//                 STRING\n//             ],\n//             label: [\n//                 STRING\n//             ]\n//         ],\n//         globals: [\n//             STRING\n//         ],\n//         member: {\n//             STRING: NUMBER\n//         },\n//         unuseds: [\n//             {\n//                 name: STRING,\n//                 line: NUMBER\n//             }\n//         ],\n//         implieds: [\n//             {\n//                 name: STRING,\n//                 line: NUMBER\n//             }\n//         ],\n//         urls: [\n//             STRING\n//         ],\n//         json: BOOLEAN\n//     }\n\n// Empty arrays will not be included.\n\n// You can obtain the parse tree that JSLint constructed while parsing. The\n// latest tree is kept in JSLINT.tree. A nice stringication can be produced\n// with\n\n//     JSON.stringify(JSLINT.tree, [\n//         'value',  'arity', 'name',  'first',\n//         'second', 'third', 'block', 'else'\n//     ], 4));\n\n// JSLint provides three directives. They look like slashstar comments, and\n// allow for setting options, declaring global variables, and establishing a\n// set of allowed property names.\n\n// These directives respect function scope.\n\n// The jslint directive is a special comment that can set one or more options.\n// The current option set is\n\n//     adsafe     true, if ADsafe rules should be enforced\n//     bitwise    true, if bitwise operators should not be allowed\n//     browser    true, if the standard browser globals should be predefined\n//     cap        true, if upper case HTML should be allowed\n//     'continue' true, if the continuation statement should be tolerated\n//     css        true, if CSS workarounds should be tolerated\n//     debug      true, if debugger statements should be allowed\n//     devel      true, if logging should be allowed (console, alert, etc.)\n//     es5        true, if ES5 syntax should be allowed\n//     evil       true, if eval should be allowed\n//     forin      true, if for in statements need not filter\n//     fragment   true, if HTML fragments should be allowed\n//     indent     the indentation factor\n//     maxerr     the maximum number of errors to allow\n//     maxlen     the maximum length of a source line\n//     newcap     true, if constructor names must be capitalized\n//     node       true, if Node.js globals should be predefined\n//     nomen      true, if names should be checked\n//     on         true, if HTML event handlers should be allowed\n//     onevar     true, if only one var statement per function should be allowed\n//     passfail   true, if the scan should stop on first error\n//     plusplus   true, if increment/decrement should not be allowed\n//     regexp     true, if the . should not be allowed in regexp literals\n//     rhino      true, if the Rhino environment globals should be predefined\n//     undef      true, if variables should be declared before used\n//     safe       true, if use of some browser features should be restricted\n//     windows    true, if MS Windows-specific globals should be predefined\n//     strict     true, require the \"use strict\"; pragma\n//     sub        true, if all forms of subscript notation are tolerated\n//     white      true, if strict whitespace rules apply\n//     widget     true  if the Yahoo Widgets globals should be predefined\n\n// For example:\n\n/*jslint\n    evil: true, nomen: false, onevar: false, regexp: false, strict: true\n*/\n\n// The properties directive declares an exclusive list of property names.\n// Any properties named in the program that are not in the list will\n// produce a warning.\n\n// For example:\n\n/*properties \"\\b\", \"\\t\", \"\\n\", \"\\f\", \"\\r\", \"!=\", \"!==\", \"\\\"\", \"%\", \"'\",\n    \"(begin)\", \"(breakage)\", \"(context)\", \"(error)\", \"(global)\",\n    \"(identifier)\", \"(line)\", \"(loopage)\", \"(name)\", \"(onevar)\", \"(params)\",\n    \"(scope)\", \"(statement)\", \"(token)\", \"(verb)\", \")\", \"*\", \"+\", \"-\", \"\\/\",\n    \";\", \"<\", \"<=\", \"==\", \"===\", \">\", \">=\", ADSAFE, ActiveXObject,\n    Array, Boolean, Buffer, COM, CScript, Canvas, CustomAnimation, Date,\n    Debug, E, Enumerator, Error, EvalError, FadeAnimation, Flash, FormField,\n    Frame, Function, HotKey, Image, JSON, LN10, LN2, LOG10E, LOG2E,\n    MAX_VALUE, MIN_VALUE, Math, MenuItem, MoveAnimation, NEGATIVE_INFINITY,\n    Number, Object, Option, PI, POSITIVE_INFINITY, Point, RangeError,\n    Rectangle, ReferenceError, RegExp, ResizeAnimation, RotateAnimation,\n    SQRT1_2, SQRT2, ScrollBar, String, Style, SyntaxError, System, Text,\n    TextArea, Timer, TypeError, URIError, URL, VBArray, WScript, Web,\n    Window, XMLDOM, XMLHttpRequest, \"\\\\\", __dirname, __filename, a,\n    a_function, a_label, a_not_allowed, a_not_defined, a_scope, abbr,\n    acronym, activeborder, activecaption, address, adsafe, adsafe_a,\n    adsafe_autocomplete, adsafe_bad_id, adsafe_div, adsafe_fragment,\n    adsafe_go, adsafe_html, adsafe_id, adsafe_id_go, adsafe_lib,\n    adsafe_lib_second, adsafe_missing_id, adsafe_name_a, adsafe_placement,\n    adsafe_prefix_a, adsafe_script, adsafe_source, adsafe_subscript_a,\n    adsafe_tag, alert, aliceblue, all, already_defined, and, animator,\n    antiquewhite, appleScript, applet, apply, approved, appworkspace, aqua,\n    aquamarine, area, arguments, arity, article, aside, assign,\n    assign_exception, assignment_function_expression, at, attribute_case_a,\n    audio, autocomplete, avoid_a, azure, b, background,\n    \"background-attachment\", \"background-color\", \"background-image\",\n    \"background-position\", \"background-repeat\", bad_assignment, bad_color_a,\n    bad_constructor, bad_entity, bad_html, bad_id_a, bad_in_a,\n    bad_invocation, bad_name_a, bad_new, bad_number, bad_operand, bad_type,\n    bad_url, bad_wrap, base, bdo, beep, beige, big, bisque, bitwise, black,\n    blanchedalmond, block, blockquote, blue, blueviolet, body, border,\n    \"border-bottom\", \"border-bottom-color\", \"border-bottom-style\",\n    \"border-bottom-width\", \"border-collapse\", \"border-color\", \"border-left\",\n    \"border-left-color\", \"border-left-style\", \"border-left-width\",\n    \"border-right\", \"border-right-color\", \"border-right-style\",\n    \"border-right-width\", \"border-spacing\", \"border-style\", \"border-top\",\n    \"border-top-color\", \"border-top-style\", \"border-top-width\",\n    \"border-width\", bottom, br, braille, brown, browser, burlywood, button,\n    buttonface, buttonhighlight, buttonshadow, buttontext, bytesToUIString,\n    c, cadetblue, call, callee, caller, canvas, cap, caption,\n    \"caption-side\", captiontext, center, charAt, charCodeAt, character,\n    chartreuse, chocolate, chooseColor, chooseFile, chooseFolder, cite,\n    clear, clearInterval, clearTimeout, clearTimout, clip, closeWidget,\n    closure, cm, code, col, colgroup, color, combine_var, command, comment,\n    comments, concat, conditional_assignment, confirm, confusing_a,\n    confusing_regexp, console, constructor, constructor_name_a, content,\n    continue, control_a, convertPathToHFS, convertPathToPlatform, coral,\n    cornflowerblue, cornsilk, \"counter-increment\", \"counter-reset\", create,\n    crimson, css, cursor, cyan, d, dangerous_comment, dangling_a, darkblue,\n    darkcyan, darkgoldenrod, darkgray, darkgreen, darkkhaki, darkmagenta,\n    darkolivegreen, darkorange, darkorchid, darkred, darksalmon,\n    darkseagreen, darkslateblue, darkslategray, darkturquoise, darkviolet,\n    data, datalist, dd, debug, decodeURI, decodeURIComponent, deeppink,\n    deepskyblue, defineClass, del, deleted, deserialize, details, devel,\n    dfn, dialog, dimgray, dir, direction, display, disrupt, div, dl,\n    document, dodgerblue, dt, duplicate_a, edge, edition, else, em, embed,\n    embossed, empty, \"empty-cells\", empty_block, empty_case, empty_class,\n    encodeURI, encodeURIComponent, entityify, errors, es5, escape, eval,\n    event, evidence, evil, ex, exception, exec, expected_a,\n    expected_a_at_b_c, expected_a_b, expected_a_b_from_c_d, expected_at_a,\n    expected_attribute_a, expected_attribute_value_a, expected_class_a,\n    expected_fraction_a, expected_id_a, expected_identifier_a,\n    expected_identifier_a_reserved, expected_lang_a, expected_linear_a,\n    expected_media_a, expected_name_a, expected_nonstandard_style_attribute,\n    expected_number_a, expected_operator_a, expected_percent_a,\n    expected_positive_a, expected_pseudo_a, expected_selector_a,\n    expected_small_a, expected_space_a_b, expected_string_a,\n    expected_style_attribute, expected_style_pattern, expected_tagname_a,\n    fieldset, figure, filesystem, filter, firebrick, first, float, floor,\n    floralwhite, focusWidget, font, \"font-family\", \"font-size\",\n    \"font-size-adjust\", \"font-stretch\", \"font-style\", \"font-variant\",\n    \"font-weight\", footer, for_if, forestgreen, forin, form, fragment,\n    frame, frames, frameset, from, fromCharCode, fuchsia, fud, funct,\n    function, function_block, function_eval, function_loop,\n    function_statement, function_strict, functions, g, gainsboro, gc,\n    get_set, ghostwhite, global, globals, gold, goldenrod, gray, graytext,\n    green, greenyellow, h1, h2, h3, h4, h5, h6, handheld, hasOwnProperty,\n    head, header, height, help, hgroup, highlight, highlighttext, history,\n    honeydew, hotpink, hr, \"hta:application\", html, html_confusion_a,\n    html_handlers, i, iTunes, id, identifier, identifier_function, iframe,\n    img, immed, implied_evil, implieds, in, inactiveborder, inactivecaption,\n    inactivecaptiontext, include, indent, indexOf, indianred, indigo,\n    infix_in, infobackground, infotext, init, input, ins, insecure_a,\n    isAlpha, isApplicationRunning, isArray, isDigit, isFinite, isNaN, ivory,\n    join, jslint, json, kbd, keygen, keys, khaki, konfabulatorVersion,\n    label, label_a_b, labeled, lang, lavender, lavenderblush, lawngreen,\n    lbp, leading_decimal_a, led, left, legend, lemonchiffon, length,\n    \"letter-spacing\", li, lib, lightblue, lightcoral, lightcyan,\n    lightgoldenrodyellow, lightgreen, lightpink, lightsalmon, lightseagreen,\n    lightskyblue, lightslategray, lightsteelblue, lightyellow, lime,\n    limegreen, line, \"line-height\", linen, link, \"list-style\",\n    \"list-style-image\", \"list-style-position\", \"list-style-type\", load,\n    loadClass, location, log, m, magenta, map, margin, \"margin-bottom\",\n    \"margin-left\", \"margin-right\", \"margin-top\", mark, \"marker-offset\",\n    maroon, match, \"max-height\", \"max-width\", maxerr, maxlen, md5,\n    mediumaquamarine, mediumblue, mediumorchid, mediumpurple,\n    mediumseagreen, mediumslateblue, mediumspringgreen, mediumturquoise,\n    mediumvioletred, member, menu, menutext, message, meta, meter,\n    midnightblue, \"min-height\", \"min-width\", mintcream, missing_a,\n    missing_a_after_b, missing_option, missing_property, missing_space_a_b,\n    missing_url, missing_use_strict, mistyrose, mixed, mm, moccasin, mode,\n    module, move_invocation, move_var, name, name_function, nav,\n    navajowhite, navigator, navy, nested_comment, newcap, next, node,\n    noframes, nomen, noscript, not, not_a_constructor, not_a_defined,\n    not_a_function, not_a_label, not_a_scope, not_greater, nud, object, ol,\n    oldlace, olive, olivedrab, on, onevar, opacity, open, openURL, opera,\n    optgroup, option, orange, orangered, orchid, outer, outline,\n    \"outline-color\", \"outline-style\", \"outline-width\", output, overflow,\n    \"overflow-x\", \"overflow-y\", p, padding, \"padding-bottom\",\n    \"padding-left\", \"padding-right\", \"padding-top\", \"page-break-after\",\n    \"page-break-before\", palegoldenrod, palegreen, paleturquoise,\n    palevioletred, papayawhip, param, parameter_a_get_b, parameter_set_a,\n    paren, parent, parseFloat, parseInt, passfail, pc, peachpuff, peru,\n    pink, play, plum, plusplus, pop, popupMenu, position, postscript,\n    powderblue, pre, predef, preferenceGroups, preferences, prev, print,\n    process, progress, projection, prompt, prototype, pt, purple, push, px,\n    q, querystring, quit, quote, quotes, radix, random, range, raw,\n    readFile, readUrl, read_only, reason, red, redefinition_a, regexp,\n    reloadWidget, replace, report, require, reserved, reserved_a,\n    resolvePath, resumeUpdates, rhino, right, rosybrown, royalblue, rp, rt,\n    ruby, runCommand, runCommandInBg, saddlebrown, safe, salmon, samp,\n    sandybrown, saveAs, savePreferences, scanned_a_b, screen, script,\n    scrollbar, seagreen, seal, search, seashell, second, section, select,\n    serialize, setInterval, setTimeout, shift, showWidgetPreferences,\n    sienna, silver, skyblue, slash_equal, slateblue, slategray, sleep,\n    slice, small, snow, sort, source, span, spawn, speak, speech, split,\n    springgreen, src, stack, statement_block, steelblue, stopping,\n    strange_loop, strict, strong, style, styleproperty, sub, subscript,\n    substr, sup, supplant, suppressUpdates, sync, system, table,\n    \"table-layout\", tag_a_in_b, tan, tbody, td, teal, tellWidget, test,\n    \"text-align\", \"text-decoration\", \"text-indent\", \"text-shadow\",\n    \"text-transform\", textarea, tfoot, th, thead, third, thistle,\n    threeddarkshadow, threedface, threedhighlight, threedlightshadow,\n    threedshadow, thru, time, title, toLowerCase, toString, toUpperCase,\n    toint32, token, tomato, too_long, too_many, top, tr, trailing_decimal_a,\n    tree, tt, tty, turquoise, tv, type, u, ul, unclosed, unclosed_comment,\n    unclosed_regexp, undef, unescape, unescaped_a, unexpected_a,\n    unexpected_char_a_b, unexpected_comment, unexpected_member_a,\n    unexpected_space_a_b, \"unicode-bidi\", unnecessary_initialize,\n    unnecessary_use, unreachable_a_b, unrecognized_style_attribute_a,\n    unrecognized_tag_a, unsafe, unused, unwatch, updateNow, url, urls,\n    use_array, use_braces, use_object, used_before_a, util, value, valueOf,\n    var, var_a_not, version, \"vertical-align\", video, violet, visibility,\n    was, watch, weird_assignment, weird_condition, weird_new, weird_program,\n    weird_relation, weird_ternary, wheat, white, \"white-space\", whitesmoke,\n    widget, width, window, windowframe, windows, windowtext, \"word-spacing\",\n    \"word-wrap\", wrap, wrap_immediate, wrap_regexp, write_is_wrong,\n    yahooCheckLogin, yahooLogin, yahooLogout, yellow, yellowgreen,\n    \"z-index\"\n*/\n\n// The global directive is used to declare global variables that can\n// be accessed by the program. If a declaration is true, then the variable\n// is writeable. Otherwise, it is read-only.\n\n// We build the application inside a function so that we produce only a single\n// global variable. That function will be invoked immediately, and its return\n// value is the JSLINT function itself. That function is also an object that\n// can contain data and other functions.\n\nvar JSLINT = (function () {\n    \"use strict\";\n\n    var adsafe_id,      // The widget's ADsafe id.\n        adsafe_may,     // The widget may load approved scripts.\n        adsafe_top,     // At the top of the widget script.\n        adsafe_went,    // ADSAFE.go has been called.\n        anonname,       // The guessed name for anonymous functions.\n        approved,       // ADsafe approved urls.\n\n// These are operators that should not be used with the ! operator.\n\n        bang = {\n            '<'  : true,\n            '<=' : true,\n            '==' : true,\n            '===': true,\n            '!==': true,\n            '!=' : true,\n            '>'  : true,\n            '>=' : true,\n            '+'  : true,\n            '-'  : true,\n            '*'  : true,\n            '/'  : true,\n            '%'  : true\n        },\n\n// These are property names that should not be permitted in the safe subset.\n\n        banned = {\n            'arguments' : true,\n            callee      : true,\n            caller      : true,\n            constructor : true,\n            'eval'      : true,\n            prototype   : true,\n            stack       : true,\n            unwatch     : true,\n            valueOf     : true,\n            watch       : true\n        },\n        begin,          // The root token\n\n// browser contains a set of global names that are commonly provided by a\n// web browser environment.\n\n        browser = {\n            clearInterval  : false,\n            clearTimeout   : false,\n            document       : false,\n            event          : false,\n            frames         : false,\n            history        : false,\n            Image          : false,\n            location       : false,\n            name           : false,\n            navigator      : false,\n            Option         : false,\n            parent         : false,\n            screen         : false,\n            setInterval    : false,\n            setTimeout     : false,\n            window         : false,\n            XMLHttpRequest : false\n        },\n\n// bundle contains the text messages.\n\n        bundle = {\n            a_function: \"'{a}' is a function.\",\n            a_label: \"'{a}' is a statement label.\",\n            a_not_allowed: \"'{a}' is not allowed.\",\n            a_not_defined: \"'{a}' is not defined.\",\n            a_scope: \"'{a}' used out of scope.\",\n            adsafe: \"ADsafe violation.\",\n            adsafe_a: \"ADsafe violation: '{a}'.\",\n            adsafe_autocomplete: \"ADsafe autocomplete violation.\",\n            adsafe_bad_id: \"ADSAFE violation: bad id.\",\n            adsafe_div: \"ADsafe violation: Wrap the widget in a div.\",\n            adsafe_fragment: \"ADSAFE: Use the fragment option.\",\n            adsafe_go: \"ADsafe violation: Missing ADSAFE.go.\",\n            adsafe_html: \"Currently, ADsafe does not operate on whole HTML documents. It operates on <div> fragments and .js files.\",\n            adsafe_id: \"ADsafe violation: id does not match.\",\n            adsafe_id_go: \"ADsafe violation: Missing ADSAFE.id or ADSAFE.go.\",\n            adsafe_lib: \"ADsafe lib violation.\",\n            adsafe_lib_second: \"ADsafe: The second argument to lib must be a function.\",\n            adsafe_missing_id: \"ADSAFE violation: missing ID_.\",\n            adsafe_name_a: \"ADsafe name violation: '{a}'.\",\n            adsafe_placement: \"ADsafe script placement violation.\",\n            adsafe_prefix_a: \"ADsafe violation: An id must have a '{a}' prefix\",\n            adsafe_script: \"ADsafe script violation.\",\n            adsafe_source: \"ADsafe unapproved script source.\",\n            adsafe_subscript_a: \"ADsafe subscript '{a}'.\",\n            adsafe_tag: \"ADsafe violation: Disallowed tag '{a}'.\",\n            already_defined: \"'{a}' is already defined.\",\n            and: \"The '&&' subexpression should be wrapped in parens.\",\n            assign_exception: \"Do not assign to the exception parameter.\",\n            assignment_function_expression: \"Expected an assignment or function call and instead saw an expression.\",\n            attribute_case_a: \"Attribute '{a}' not all lower case.\",\n            avoid_a: \"Avoid '{a}'.\",\n            bad_assignment: \"Bad assignment.\",\n            bad_color_a: \"Bad hex color '{a}'.\",\n            bad_constructor: \"Bad constructor.\",\n            bad_entity: \"Bad entity.\",\n            bad_html: \"Bad HTML string\",\n            bad_id_a: \"Bad id: '{a}'.\",\n            bad_in_a: \"Bad for in variable '{a}'.\",\n            bad_invocation: \"Bad invocation.\",\n            bad_name_a: \"Bad name: '{a}'.\",\n            bad_new: \"Do not use 'new' for side effects.\",\n            bad_number: \"Bad number '{a}'.\",\n            bad_operand: \"Bad operand.\",\n            bad_type: \"Bad type.\",\n            bad_url: \"Bad url string.\",\n            bad_wrap: \"Do not wrap function literals in parens unless they are to be immediately invoked.\",\n            combine_var: \"Combine this with the previous 'var' statement.\",\n            conditional_assignment: \"Expected a conditional expression and instead saw an assignment.\",\n            confusing_a: \"Confusing use of '{a}'.\",\n            confusing_regexp: \"Confusing regular expression.\",\n            constructor_name_a: \"A constructor name '{a}' should start with an uppercase letter.\",\n            control_a: \"Unexpected control character '{a}'.\",\n            css: \"A css file should begin with @charset 'UTF-8';\",\n            dangling_a: \"Unexpected dangling '_' in '{a}'.\",\n            dangerous_comment: \"Dangerous comment.\",\n            deleted: \"Only properties should be deleted.\",\n            duplicate_a: \"Duplicate '{a}'.\",\n            empty_block: \"Empty block.\",\n            empty_case: \"Empty case.\",\n            empty_class: \"Empty class.\",\n            evil: \"eval is evil.\",\n            expected_a: \"Expected '{a}'.\",\n            expected_a_b: \"Expected '{a}' and instead saw '{b}'.\",\n            expected_a_b_from_c_d: \"Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.\",\n            expected_at_a: \"Expected an at-rule, and instead saw @{a}.\",\n            expected_a_at_b_c: \"Expected '{a}' at column {b}, not column {c}.\",\n            expected_attribute_a: \"Expected an attribute, and instead saw [{a}].\",\n            expected_attribute_value_a: \"Expected an attribute value and instead saw '{a}'.\",\n            expected_class_a: \"Expected a class, and instead saw .{a}.\",\n            expected_fraction_a: \"Expected a number between 0 and 1 and instead saw '{a}'\",\n            expected_id_a: \"Expected an id, and instead saw #{a}.\",\n            expected_identifier_a: \"Expected an identifier and instead saw '{a}'.\",\n            expected_identifier_a_reserved: \"Expected an identifier and instead saw '{a}' (a reserved word).\",\n            expected_linear_a: \"Expected a linear unit and instead saw '{a}'.\",\n            expected_lang_a: \"Expected a lang code, and instead saw :{a}.\",\n            expected_media_a: \"Expected a CSS media type, and instead saw '{a}'.\",\n            expected_name_a: \"Expected a name and instead saw '{a}'.\",\n            expected_nonstandard_style_attribute: \"Expected a non-standard style attribute and instead saw '{a}'.\",\n            expected_number_a: \"Expected a number and instead saw '{a}'.\",\n            expected_operator_a: \"Expected an operator and instead saw '{a}'.\",\n            expected_percent_a: \"Expected a percentage and instead saw '{a}'\",\n            expected_positive_a: \"Expected a positive number and instead saw '{a}'\",\n            expected_pseudo_a: \"Expected a pseudo, and instead saw :{a}.\",\n            expected_selector_a: \"Expected a CSS selector, and instead saw {a}.\",\n            expected_small_a: \"Expected a small number and instead saw '{a}'\",\n            expected_space_a_b: \"Expected exactly one space between '{a}' and '{b}'.\",\n            expected_string_a: \"Expected a string and instead saw {a}.\",\n            expected_style_attribute: \"Excepted a style attribute, and instead saw '{a}'.\",\n            expected_style_pattern: \"Expected a style pattern, and instead saw '{a}'.\",\n            expected_tagname_a: \"Expected a tagName, and instead saw {a}.\",\n            for_if: \"The body of a for in should be wrapped in an if statement to filter unwanted properties from the prototype.\",\n            function_block: \"Function statements should not be placed in blocks. \" +\n                \"Use a function expression or move the statement to the top of \" +\n                \"the outer function.\",\n            function_eval: \"The Function constructor is eval.\",\n            function_loop: \"Don't make functions within a loop.\",\n            function_statement: \"Function statements are not invocable. \" +\n                \"Wrap the whole function invocation in parens.\",\n            function_strict: \"Use the function form of \\\"use strict\\\".\",\n            get_set: \"get/set are ES5 features.\",\n            html_confusion_a: \"HTML confusion in regular expression '<{a}'.\",\n            html_handlers: \"Avoid HTML event handlers.\",\n            identifier_function: \"Expected an identifier in an assignment and instead saw a function invocation.\",\n            implied_evil: \"Implied eval is evil. Pass a function instead of a string.\",\n            infix_in: \"Unexpected 'in'. Compare with undefined, or use the hasOwnProperty method instead.\",\n            insecure_a: \"Insecure '{a}'.\",\n            isNaN: \"Use the isNaN function to compare with NaN.\",\n            label_a_b: \"Label '{a}' on '{b}' statement.\",\n            lang: \"lang is deprecated.\",\n            leading_decimal_a: \"A leading decimal point can be confused with a dot: '.{a}'.\",\n            missing_a: \"Missing '{a}'.\",\n            missing_a_after_b: \"Missing '{a}' after '{b}'.\",\n            missing_option: \"Missing option value.\",\n            missing_property: \"Missing property name.\",\n            missing_space_a_b: \"Missing space between '{a}' and '{b}'.\",\n            missing_url: \"Missing url.\",\n            missing_use_strict: \"Missing \\\"use strict\\\" statement.\",\n            mixed: \"Mixed spaces and tabs.\",\n            move_invocation: \"Move the invocation into the parens that contain the function.\",\n            move_var: \"Move 'var' declarations to the top of the function.\",\n            name_function: \"Missing name in function statement.\",\n            nested_comment: \"Nested comment.\",\n            not: \"Nested not.\",\n            not_a_constructor: \"Do not use {a} as a constructor.\",\n            not_a_defined: \"'{a}' has not been fully defined yet.\",\n            not_a_function: \"'{a}' is not a function.\",\n            not_a_label: \"'{a}' is not a label.\",\n            not_a_scope: \"'{a}' is out of scope.\",\n            not_greater: \"'{a}' should not be greater than '{b}'.\",\n            parameter_a_get_b: \"Unexpected parameter '{a}' in get {b} function.\",\n            parameter_set_a: \"Expected parameter (value) in set {a} function.\",\n            radix: \"Missing radix parameter.\",\n            read_only: \"Read only.\",\n            redefinition_a: \"Redefinition of '{a}'.\",\n            reserved_a: \"Reserved name '{a}'.\",\n            scanned_a_b: \"{a} ({b}% scanned).\",\n            slash_equal: \"A regular expression literal can be confused with '/='.\",\n            statement_block: \"Expected to see a statement and instead saw a block.\",\n            stopping: \"Stopping. \",\n            strange_loop: \"Strange loop.\",\n            strict: \"Strict violation.\",\n            subscript: \"['{a}'] is better written in dot notation.\",\n            tag_a_in_b: \"A '<{a}>' must be within '<{b}>'.\",\n            too_long: \"Line too long.\",\n            too_many: \"Too many errors.\",\n            trailing_decimal_a: \"A trailing decimal point can be confused with a dot: '.{a}'.\",\n            type: \"type is unnecessary.\",\n            unclosed: \"Unclosed string.\",\n            unclosed_comment: \"Unclosed comment.\",\n            unclosed_regexp: \"Unclosed regular expression.\",\n            unescaped_a: \"Unescaped '{a}'.\",\n            unexpected_a: \"Unexpected '{a}'.\",\n            unexpected_char_a_b: \"Unexpected character '{a}' in {b}.\",\n            unexpected_comment: \"Unexpected comment.\",\n            unexpected_member_a: \"Unexpected property '{a}'.\",\n            unexpected_space_a_b: \"Unexpected space between '{a}' and '{b}'.\",\n            unnecessary_initialize: \"It is not necessary to initialize '{a}' to 'undefined'.\",\n            unnecessary_use: \"Unnecessary \\\"use strict\\\".\",\n            unreachable_a_b: \"Unreachable '{a}' after '{b}'.\",\n            unrecognized_style_attribute_a: \"Unrecognized style attribute '{a}'.\",\n            unrecognized_tag_a: \"Unrecognized tag '<{a}>'.\",\n            unsafe: \"Unsafe character.\",\n            url: \"JavaScript URL.\",\n            use_array: \"Use the array literal notation [].\",\n            use_braces: \"Spaces are hard to count. Use {{a}}.\",\n            use_object: \"Use the object literal notation {}.\",\n            used_before_a: \"'{a}' was used before it was defined.\",\n            var_a_not: \"Variable {a} was not declared correctly.\",\n            weird_assignment: \"Weird assignment.\",\n            weird_condition: \"Weird condition.\",\n            weird_new: \"Weird construction. Delete 'new'.\",\n            weird_program: \"Weird program.\",\n            weird_relation: \"Weird relation.\",\n            weird_ternary: \"Weird ternary.\",\n            wrap_immediate: \"Wrap an immediate function invocation in parentheses \" +\n                \"to assist the reader in understanding that the expression \" +\n                \"is the result of a function, and not the function itself.\",\n            wrap_regexp: \"Wrap the /regexp/ literal in parens to disambiguate the slash operator.\",\n            write_is_wrong: \"document.write can be a form of eval.\"\n        },\n        comments_off,\n        css_attribute_data,\n        css_any,\n\n        css_colorData = {\n            \"aliceblue\"             : true,\n            \"antiquewhite\"          : true,\n            \"aqua\"                  : true,\n            \"aquamarine\"            : true,\n            \"azure\"                 : true,\n            \"beige\"                 : true,\n            \"bisque\"                : true,\n            \"black\"                 : true,\n            \"blanchedalmond\"        : true,\n            \"blue\"                  : true,\n            \"blueviolet\"            : true,\n            \"brown\"                 : true,\n            \"burlywood\"             : true,\n            \"cadetblue\"             : true,\n            \"chartreuse\"            : true,\n            \"chocolate\"             : true,\n            \"coral\"                 : true,\n            \"cornflowerblue\"        : true,\n            \"cornsilk\"              : true,\n            \"crimson\"               : true,\n            \"cyan\"                  : true,\n            \"darkblue\"              : true,\n            \"darkcyan\"              : true,\n            \"darkgoldenrod\"         : true,\n            \"darkgray\"              : true,\n            \"darkgreen\"             : true,\n            \"darkkhaki\"             : true,\n            \"darkmagenta\"           : true,\n            \"darkolivegreen\"        : true,\n            \"darkorange\"            : true,\n            \"darkorchid\"            : true,\n            \"darkred\"               : true,\n            \"darksalmon\"            : true,\n            \"darkseagreen\"          : true,\n            \"darkslateblue\"         : true,\n            \"darkslategray\"         : true,\n            \"darkturquoise\"         : true,\n            \"darkviolet\"            : true,\n            \"deeppink\"              : true,\n            \"deepskyblue\"           : true,\n            \"dimgray\"               : true,\n            \"dodgerblue\"            : true,\n            \"firebrick\"             : true,\n            \"floralwhite\"           : true,\n            \"forestgreen\"           : true,\n            \"fuchsia\"               : true,\n            \"gainsboro\"             : true,\n            \"ghostwhite\"            : true,\n            \"gold\"                  : true,\n            \"goldenrod\"             : true,\n            \"gray\"                  : true,\n            \"green\"                 : true,\n            \"greenyellow\"           : true,\n            \"honeydew\"              : true,\n            \"hotpink\"               : true,\n            \"indianred\"             : true,\n            \"indigo\"                : true,\n            \"ivory\"                 : true,\n            \"khaki\"                 : true,\n            \"lavender\"              : true,\n            \"lavenderblush\"         : true,\n            \"lawngreen\"             : true,\n            \"lemonchiffon\"          : true,\n            \"lightblue\"             : true,\n            \"lightcoral\"            : true,\n            \"lightcyan\"             : true,\n            \"lightgoldenrodyellow\"  : true,\n            \"lightgreen\"            : true,\n            \"lightpink\"             : true,\n            \"lightsalmon\"           : true,\n            \"lightseagreen\"         : true,\n            \"lightskyblue\"          : true,\n            \"lightslategray\"        : true,\n            \"lightsteelblue\"        : true,\n            \"lightyellow\"           : true,\n            \"lime\"                  : true,\n            \"limegreen\"             : true,\n            \"linen\"                 : true,\n            \"magenta\"               : true,\n            \"maroon\"                : true,\n            \"mediumaquamarine\"      : true,\n            \"mediumblue\"            : true,\n            \"mediumorchid\"          : true,\n            \"mediumpurple\"          : true,\n            \"mediumseagreen\"        : true,\n            \"mediumslateblue\"       : true,\n            \"mediumspringgreen\"     : true,\n            \"mediumturquoise\"       : true,\n            \"mediumvioletred\"       : true,\n            \"midnightblue\"          : true,\n            \"mintcream\"             : true,\n            \"mistyrose\"             : true,\n            \"moccasin\"              : true,\n            \"navajowhite\"           : true,\n            \"navy\"                  : true,\n            \"oldlace\"               : true,\n            \"olive\"                 : true,\n            \"olivedrab\"             : true,\n            \"orange\"                : true,\n            \"orangered\"             : true,\n            \"orchid\"                : true,\n            \"palegoldenrod\"         : true,\n            \"palegreen\"             : true,\n            \"paleturquoise\"         : true,\n            \"palevioletred\"         : true,\n            \"papayawhip\"            : true,\n            \"peachpuff\"             : true,\n            \"peru\"                  : true,\n            \"pink\"                  : true,\n            \"plum\"                  : true,\n            \"powderblue\"            : true,\n            \"purple\"                : true,\n            \"red\"                   : true,\n            \"rosybrown\"             : true,\n            \"royalblue\"             : true,\n            \"saddlebrown\"           : true,\n            \"salmon\"                : true,\n            \"sandybrown\"            : true,\n            \"seagreen\"              : true,\n            \"seashell\"              : true,\n            \"sienna\"                : true,\n            \"silver\"                : true,\n            \"skyblue\"               : true,\n            \"slateblue\"             : true,\n            \"slategray\"             : true,\n            \"snow\"                  : true,\n            \"springgreen\"           : true,\n            \"steelblue\"             : true,\n            \"tan\"                   : true,\n            \"teal\"                  : true,\n            \"thistle\"               : true,\n            \"tomato\"                : true,\n            \"turquoise\"             : true,\n            \"violet\"                : true,\n            \"wheat\"                 : true,\n            \"white\"                 : true,\n            \"whitesmoke\"            : true,\n            \"yellow\"                : true,\n            \"yellowgreen\"           : true,\n\n            \"activeborder\"          : true,\n            \"activecaption\"         : true,\n            \"appworkspace\"          : true,\n            \"background\"            : true,\n            \"buttonface\"            : true,\n            \"buttonhighlight\"       : true,\n            \"buttonshadow\"          : true,\n            \"buttontext\"            : true,\n            \"captiontext\"           : true,\n            \"graytext\"              : true,\n            \"highlight\"             : true,\n            \"highlighttext\"         : true,\n            \"inactiveborder\"        : true,\n            \"inactivecaption\"       : true,\n            \"inactivecaptiontext\"   : true,\n            \"infobackground\"        : true,\n            \"infotext\"              : true,\n            \"menu\"                  : true,\n            \"menutext\"              : true,\n            \"scrollbar\"             : true,\n            \"threeddarkshadow\"      : true,\n            \"threedface\"            : true,\n            \"threedhighlight\"       : true,\n            \"threedlightshadow\"     : true,\n            \"threedshadow\"          : true,\n            \"window\"                : true,\n            \"windowframe\"           : true,\n            \"windowtext\"            : true\n        },\n\n        css_border_style,\n        css_break,\n\n        css_lengthData = {\n            '%': true,\n            'cm': true,\n            'em': true,\n            'ex': true,\n            'in': true,\n            'mm': true,\n            'pc': true,\n            'pt': true,\n            'px': true\n        },\n\n        css_media,\n        css_overflow,\n\n        devel = {\n            alert           : false,\n            confirm         : false,\n            console         : false,\n            Debug           : false,\n            opera           : false,\n            prompt          : false\n        },\n\n        escapes = {\n            '\\b': '\\\\b',\n            '\\t': '\\\\t',\n            '\\n': '\\\\n',\n            '\\f': '\\\\f',\n            '\\r': '\\\\r',\n            '\"' : '\\\\\"',\n            '/' : '\\\\/',\n            '\\\\': '\\\\\\\\'\n        },\n\n        funct,          // The current function\n\n        functionicity = [\n            'closure', 'exception', 'global', 'label', 'outer', 'unused', 'var'\n        ],\n\n        functions,      // All of the functions\n        global,         // The global scope\n        html_tag = {\n            a:        {},\n            abbr:     {},\n            acronym:  {},\n            address:  {},\n            applet:   {},\n            area:     {empty: true, parent: ' map '},\n            article:  {},\n            aside:    {},\n            audio:    {},\n            b:        {},\n            base:     {empty: true, parent: ' head '},\n            bdo:      {},\n            big:      {},\n            blockquote: {},\n            body:     {parent: ' html noframes '},\n            br:       {empty: true},\n            button:   {},\n            canvas:   {parent: ' body p div th td '},\n            caption:  {parent: ' table '},\n            center:   {},\n            cite:     {},\n            code:     {},\n            col:      {empty: true, parent: ' table colgroup '},\n            colgroup: {parent: ' table '},\n            command:  {parent: ' menu '},\n            datalist: {},\n            dd:       {parent: ' dl '},\n            del:      {},\n            details:  {},\n            dialog:   {},\n            dfn:      {},\n            dir:      {},\n            div:      {},\n            dl:       {},\n            dt:       {parent: ' dl '},\n            em:       {},\n            embed:    {},\n            fieldset: {},\n            figure:   {},\n            font:     {},\n            footer:   {},\n            form:     {},\n            frame:    {empty: true, parent: ' frameset '},\n            frameset: {parent: ' html frameset '},\n            h1:       {},\n            h2:       {},\n            h3:       {},\n            h4:       {},\n            h5:       {},\n            h6:       {},\n            head:     {parent: ' html '},\n            header:   {},\n            hgroup:   {},\n            hr:       {empty: true},\n            'hta:application':\n                      {empty: true, parent: ' head '},\n            html:     {parent: '*'},\n            i:        {},\n            iframe:   {},\n            img:      {empty: true},\n            input:    {empty: true},\n            ins:      {},\n            kbd:      {},\n            keygen:   {},\n            label:    {},\n            legend:   {parent: ' details fieldset figure '},\n            li:       {parent: ' dir menu ol ul '},\n            link:     {empty: true, parent: ' head '},\n            map:      {},\n            mark:     {},\n            menu:     {},\n            meta:     {empty: true, parent: ' head noframes noscript '},\n            meter:    {},\n            nav:      {},\n            noframes: {parent: ' html body '},\n            noscript: {parent: ' body head noframes '},\n            object:   {},\n            ol:       {},\n            optgroup: {parent: ' select '},\n            option:   {parent: ' optgroup select '},\n            output:   {},\n            p:        {},\n            param:    {empty: true, parent: ' applet object '},\n            pre:      {},\n            progress: {},\n            q:        {},\n            rp:       {},\n            rt:       {},\n            ruby:     {},\n            samp:     {},\n            script:   {empty: true, parent: ' body div frame head iframe p pre span '},\n            section:  {},\n            select:   {},\n            small:    {},\n            span:     {},\n            source:   {},\n            strong:   {},\n            style:    {parent: ' head ', empty: true},\n            sub:      {},\n            sup:      {},\n            table:    {},\n            tbody:    {parent: ' table '},\n            td:       {parent: ' tr '},\n            textarea: {},\n            tfoot:    {parent: ' table '},\n            th:       {parent: ' tr '},\n            thead:    {parent: ' table '},\n            time:     {},\n            title:    {parent: ' head '},\n            tr:       {parent: ' table tbody thead tfoot '},\n            tt:       {},\n            u:        {},\n            ul:       {},\n            'var':    {},\n            video:    {}\n        },\n\n        ids,            // HTML ids\n        implied,        // Implied globals\n        in_block,\n        indent,\n        json_mode,\n        lines,\n        lookahead,\n        member,\n        node = {\n            Buffer       : false,\n            clearInterval: false,\n            clearTimout  : false,\n            console      : false,\n            global       : false,\n            module       : false,\n            process      : false,\n            querystring  : false,\n            require      : false,\n            setInterval  : false,\n            setTimeout   : false,\n            util         : false,\n            __filename   : false,\n            __dirname    : false\n        },\n        properties,\n        next_token,\n        older_token,\n        option,\n        predefined,     // Global variables defined by option\n        prereg,\n        prev_token,\n        regexp_flag = {\n            g: true,\n            i: true,\n            m: true\n        },\n        rhino = {\n            defineClass : false,\n            deserialize : false,\n            gc          : false,\n            help        : false,\n            load        : false,\n            loadClass   : false,\n            print       : false,\n            quit        : false,\n            readFile    : false,\n            readUrl     : false,\n            runCommand  : false,\n            seal        : false,\n            serialize   : false,\n            spawn       : false,\n            sync        : false,\n            toint32     : false,\n            version     : false\n        },\n\n        scope,      // The current scope\n        semicolon_coda = {\n            ';' : true,\n            '\"' : true,\n            '\\'': true,\n            ')' : true\n        },\n        src,\n        stack,\n\n// standard contains the global names that are provided by the\n// ECMAScript standard.\n\n        standard = {\n            Array               : false,\n            Boolean             : false,\n            Date                : false,\n            decodeURI           : false,\n            decodeURIComponent  : false,\n            encodeURI           : false,\n            encodeURIComponent  : false,\n            Error               : false,\n            'eval'              : false,\n            EvalError           : false,\n            Function            : false,\n            hasOwnProperty      : false,\n            isFinite            : false,\n            isNaN               : false,\n            JSON                : false,\n            Math                : false,\n            Number              : false,\n            Object              : false,\n            parseInt            : false,\n            parseFloat          : false,\n            RangeError          : false,\n            ReferenceError      : false,\n            RegExp              : false,\n            String              : false,\n            SyntaxError         : false,\n            TypeError           : false,\n            URIError            : false\n        },\n\n        standard_property = {\n            E                   : true,\n            LN2                 : true,\n            LN10                : true,\n            LOG2E               : true,\n            LOG10E              : true,\n            MAX_VALUE           : true,\n            MIN_VALUE           : true,\n            NEGATIVE_INFINITY   : true,\n            PI                  : true,\n            POSITIVE_INFINITY   : true,\n            SQRT1_2             : true,\n            SQRT2               : true\n        },\n\n        strict_mode,\n        syntax = {},\n        tab,\n        token,\n        urls,\n        var_mode,\n        warnings,\n\n// widget contains the global names which are provided to a Yahoo\n// (fna Konfabulator) widget.\n\n        widget = {\n            alert                   : true,\n            animator                : true,\n            appleScript             : true,\n            beep                    : true,\n            bytesToUIString         : true,\n            Canvas                  : true,\n            chooseColor             : true,\n            chooseFile              : true,\n            chooseFolder            : true,\n            closeWidget             : true,\n            COM                     : true,\n            convertPathToHFS        : true,\n            convertPathToPlatform   : true,\n            CustomAnimation         : true,\n            escape                  : true,\n            FadeAnimation           : true,\n            filesystem              : true,\n            Flash                   : true,\n            focusWidget             : true,\n            form                    : true,\n            FormField               : true,\n            Frame                   : true,\n            HotKey                  : true,\n            Image                   : true,\n            include                 : true,\n            isApplicationRunning    : true,\n            iTunes                  : true,\n            konfabulatorVersion     : true,\n            log                     : true,\n            md5                     : true,\n            MenuItem                : true,\n            MoveAnimation           : true,\n            openURL                 : true,\n            play                    : true,\n            Point                   : true,\n            popupMenu               : true,\n            preferenceGroups        : true,\n            preferences             : true,\n            print                   : true,\n            prompt                  : true,\n            random                  : true,\n            Rectangle               : true,\n            reloadWidget            : true,\n            ResizeAnimation         : true,\n            resolvePath             : true,\n            resumeUpdates           : true,\n            RotateAnimation         : true,\n            runCommand              : true,\n            runCommandInBg          : true,\n            saveAs                  : true,\n            savePreferences         : true,\n            screen                  : true,\n            ScrollBar               : true,\n            showWidgetPreferences   : true,\n            sleep                   : true,\n            speak                   : true,\n            Style                   : true,\n            suppressUpdates         : true,\n            system                  : true,\n            tellWidget              : true,\n            Text                    : true,\n            TextArea                : true,\n            Timer                   : true,\n            unescape                : true,\n            updateNow               : true,\n            URL                     : true,\n            Web                     : true,\n            widget                  : true,\n            Window                  : true,\n            XMLDOM                  : true,\n            XMLHttpRequest          : true,\n            yahooCheckLogin         : true,\n            yahooLogin              : true,\n            yahooLogout             : true\n        },\n\n        windows = {\n            ActiveXObject: false,\n            CScript      : false,\n            Debug        : false,\n            Enumerator   : false,\n            System       : false,\n            VBArray      : false,\n            WScript      : false\n        },\n\n//  xmode is used to adapt to the exceptions in html parsing.\n//  It can have these states:\n//      false   .js script file\n//      html\n//      outer\n//      script\n//      style\n//      scriptstring\n//      styleproperty\n\n        xmode,\n        xquote,\n\n// Regular expressions. Some of these are stupidly long.\n\n// unsafe comment or string\n        ax = /@cc|<\\/?|script|\\]\\s*\\]|<\\s*!|&lt/i,\n// unsafe characters that are silently deleted by one or more browsers\n        cx = /[\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/,\n// token\n        tx = /^\\s*([(){}\\[.,:;'\"~\\?\\]#@]|==?=?|\\/(\\*(jslint|properties|members|global)?|=|\\/)?|\\*[\\/=]?|\\+(?:=|\\++)?|-(?:=|-+)?|%=?|&[&=]?|\\|[|=]?|>>?>?=?|<([\\/=!]|\\!(\\[|--)?|<=?)?|\\^=?|\\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\\.[0-9]*)?([eE][+\\-]?[0-9]+)?)/,\n// html token\n        hx = /^\\s*(['\"=>\\/&#]|<(?:\\/|\\!(?:--)?)?|[a-zA-Z][a-zA-Z0-9_\\-:]*|[0-9]+|--)/,\n// characters in strings that need escapement\n        nx = /[\\u0000-\\u001f&<\"\\/\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/,\n        nxg = /[\\u0000-\\u001f&<\"\\/\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\n// outer html token\n        ox = /[>&]|<[\\/!]?|--/,\n// star slash\n        lx = /\\*\\/|\\/\\*/,\n// identifier\n        ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/,\n// javascript url\n        jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\\s*:/i,\n// url badness\n        ux = /&|\\+|\\u00AD|\\.\\.|\\/\\*|%[^;]|base64|url|expression|data|mailto/i,\n// style\n        sx = /^\\s*([{:#%.=,>+\\[\\]@()\"';]|\\*=?|\\$=|\\|=|\\^=|~=|[a-zA-Z_][a-zA-Z0-9_\\-]*|[0-9]+|<\\/|\\/\\*)/,\n        ssx = /^\\s*([@#!\"'};:\\-%.=,+\\[\\]()*_]|[a-zA-Z][a-zA-Z0-9._\\-]*|\\/\\*?|\\d+(?:\\.\\d+)?|<\\/)/,\n// attributes characters\n        qx = /[^a-zA-Z0-9+\\-_\\/ ]/,\n// query characters for ids\n        dx = /[\\[\\]\\/\\\\\"'*<>.&:(){}+=#]/,\n\n        rx = {\n            outer: hx,\n            html: hx,\n            style: sx,\n            styleproperty: ssx\n        };\n\n\n    function return_this() {\n        return this;\n    }\n\n    function F() {}     // Used by Object.create\n\n// Provide critical ES5 functions to ES3.\n\n    if (typeof Array.prototype.filter !== 'function') {\n        Array.prototype.filter = function (f) {\n            var i, length = this.length, result = [];\n            for (i = 0; i < length; i += 1) {\n                try {\n                    result.push(f(this[i]));\n                } catch (ignore) {\n                }\n            }\n            return result;\n        };\n    }\n\n    if (typeof Array.isArray !== 'function') {\n        Array.isArray = function (o) {\n            return Object.prototype.toString.apply(o) === '[object Array]';\n        };\n    }\n\n    if (!Object.hasOwnProperty('create')) {\n        Object.create = function (o) {\n            F.prototype = o;\n            return new F();\n        };\n    }\n\n    if (typeof Object.keys !== 'function') {\n        Object.keys = function (o) {\n            var array = [], key;\n            for (key in o) {\n                if (Object.prototype.hasOwnProperty.call(o, key)) {\n                    array.push(key);\n                }\n            }\n            return array;\n        };\n    }\n\n// Substandard methods\n\n    if (typeof String.prototype.entityify !== 'function') {\n        String.prototype.entityify = function () {\n            return this\n                .replace(/&/g, '&amp;')\n                .replace(/</g, '&lt;')\n                .replace(/>/g, '&gt;');\n        };\n    }\n\n    if (typeof String.prototype.isAlpha !== 'function') {\n        String.prototype.isAlpha = function () {\n            return (this >= 'a' && this <= 'z\\uffff') ||\n                (this >= 'A' && this <= 'Z\\uffff');\n        };\n    }\n\n    if (typeof String.prototype.isDigit !== 'function') {\n        String.prototype.isDigit = function () {\n            return (this >= '0' && this <= '9');\n        };\n    }\n\n    if (typeof String.prototype.supplant !== 'function') {\n        String.prototype.supplant = function (o) {\n            return this.replace(/\\{([^{}]*)\\}/g, function (a, b) {\n                var replacement = o[b];\n                return typeof replacement === 'string' ||\n                    typeof replacement === 'number' ? replacement : a;\n            });\n        };\n    }\n\n    if (typeof String.prototype.name !== 'function') {\n        String.prototype.name = function () {\n\n// If the string looks like an identifier, then we can return it as is.\n// If the string contains no control characters, no quote characters, and no\n// backslash characters, then we can simply slap some quotes around it.\n// Otherwise we must also replace the offending characters with safe\n// sequences.\n\n            if (ix.test(this)) {\n                return this;\n            }\n            if (nx.test(this)) {\n                return '\"' + this.replace(nxg, function (a) {\n                    if (escapes[a]) {\n                        return escapes[a];\n                    }\n                    return '\\\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4);\n                }) + '\"';\n            }\n            return '\"' + this + '\"';\n        };\n    }\n\n\n    function combine(a, b) {\n        var name;\n        for (name in b) {\n            if (Object.prototype.hasOwnProperty.call(b, name)) {\n                a[name] = b[name];\n            }\n        }\n    }\n\n    function assume() {\n        if (!option.safe) {\n            if (option.rhino) {\n                combine(predefined, rhino);\n            }\n            if (option.devel) {\n                combine(predefined, devel);\n            }\n            if (option.browser) {\n                combine(predefined, browser);\n            }\n            if (option.windows) {\n                combine(predefined, windows);\n            }\n            if (option.node) {\n                combine(predefined, node);\n            }\n            if (option.widget) {\n                combine(predefined, widget);\n            }\n        }\n    }\n\n\n// Produce an error warning.\n\n    function quit(message, line, character) {\n        throw {\n            name: 'JSLintError',\n            line: line,\n            character: character,\n            message: bundle.scanned_a_b.supplant({\n                a: message,\n                b: Math.floor((line / lines.length) * 100)\n            })\n        };\n    }\n\n    function warn(message, offender, a, b, c, d) {\n        var character, line, warning;\n        offender = offender || next_token;  // `~\n        line = offender.line || 0;\n        character = offender.from || 0;\n        warning = {\n            id: '(error)',\n            raw: bundle[message] || message,\n            evidence: lines[line - 1] || '',\n            line: line,\n            character: character,\n            a: a || offender.value,\n            b: b,\n            c: c,\n            d: d\n        };\n        warning.reason = warning.raw.supplant(warning);\n        JSLINT.errors.push(warning);\n        if (option.passfail) {\n            quit(bundle.stopping, line, character);\n        }\n        warnings += 1;\n        if (warnings >= option.maxerr) {\n            quit(bundle.too_many, line, character);\n        }\n        return warning;\n    }\n\n    function warn_at(message, line, character, a, b, c, d) {\n        return warn(message, {\n            line: line,\n            from: character\n        }, a, b, c, d);\n    }\n\n    function fail(message, offender, a, b, c, d) {\n        var warning = warn(message, offender, a, b, c, d);\n        quit(bundle.stopping, warning.line, warning.character);\n    }\n\n    function fail_at(message, line, character, a, b, c, d) {\n        return fail(message, {\n            line: line,\n            from: character\n        }, a, b, c, d);\n    }\n\n    function expected_at(at) {\n        if (option.white && next_token.from !== at) {\n            warn('expected_a_at_b_c', next_token, next_token.value, at,\n                next_token.from);\n        }\n    }\n\n    function aint(it, name, expected) {\n        if (it[name] !== expected) {\n            warn('expected_a_b', it, expected, it[name]);\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n\n// lexical analysis and token construction\n\n    var lex = (function lex() {\n        var character, from, line, source_row;\n\n// Private lex methods\n\n        function collect_comment(comment, quote, line, at) {\n            var comment_object = {\n                comment: comment,\n                quote: quote,\n                at: at,\n                line: line\n            };\n            if (comments_off || src || (xmode && xmode !== 'script' &&\n                    xmode !== 'style' && xmode !== 'styleproperty')) {\n                warn_at('unexpected_comment', line, character);\n            } else if (xmode === 'script' && /<\\//i.test(source_row)) {\n                warn_at('unexpected_a', line, character, '<\\/');\n            } else if (option.safe && ax.test(comment)) {\n                warn_at('dangerous_comment', line, at);\n            }\n            if (older_token.comments) {\n                older_token.comments.push(comment_object);\n            } else {\n                older_token.comments = [comment_object];\n            }\n            JSLINT.comments.push(comment_object);\n        }\n\n        function next_line() {\n            var at;\n            if (line >= lines.length) {\n                return false;\n            }\n            character = 1;\n            source_row = lines[line];\n            line += 1;\n            at = source_row.search(/ \\t/);\n            if (at >= 0) {\n                warn_at('mixed', line, at + 1);\n            }\n            source_row = source_row.replace(/\\t/g, tab);\n            at = source_row.search(cx);\n            if (at >= 0) {\n                warn_at('unsafe', line, at);\n            }\n            if (option.maxlen && option.maxlen < source_row.length) {\n                warn_at('too_long', line, source_row.length);\n            }\n            return true;\n        }\n\n// Produce a token object.  The token inherits from a syntax symbol.\n\n        function it(type, value, quote) {\n            var id, the_token;\n            if (type === '(string)' || type === '(range)') {\n                if (jx.test(value)) {\n                    warn_at('url', line, from);\n                }\n            }\n            the_token = Object.create(syntax[(\n                type === '(punctuator)' ||\n                    (type === '(identifier)' &&\n                    Object.prototype.hasOwnProperty.call(syntax, value)) ?\n                value :\n                type\n            )] || syntax['(error)']);\n            if (type === '(identifier)') {\n                the_token.identifier = true;\n                if (value === '__iterator__' || value === '__proto__') {\n                    fail_at('reserved_a', line, from, value);\n                } else if (option.nomen &&\n                        (value.charAt(0) === '_' ||\n                        value.charAt(value.length - 1) === '_')) {\n                    warn_at('dangling_a', line, from, value);\n                }\n            }\n            if (value !== undefined) {\n                the_token.value = value;\n            }\n            if (quote) {\n                the_token.quote = quote;\n            }\n            the_token.line = line;\n            the_token.from = from;\n            the_token.thru = character;\n            the_token.prev = older_token;\n            id = the_token.id;\n            prereg = id && (\n                ('(,=:[!&|?{};'.indexOf(id.charAt(id.length - 1)) >= 0) ||\n                id === 'return'\n            );\n            older_token.next = the_token;\n            older_token = the_token;\n            return the_token;\n        }\n\n// Public lex methods\n\n        return {\n            init: function (source) {\n                if (typeof source === 'string') {\n                    lines = source\n                        .replace(/\\r\\n/g, '\\n')\n                        .replace(/\\r/g, '\\n')\n                        .split('\\n');\n                } else {\n                    lines = source;\n                }\n                line = 0;\n                next_line();\n                from = 1;\n            },\n\n            range: function (begin, end) {\n                var c, value = '';\n                from = character;\n                if (source_row.charAt(0) !== begin) {\n                    fail_at('expected_a_b', line, character, begin,\n                        source_row.charAt(0));\n                }\n                for (;;) {\n                    source_row = source_row.slice(1);\n                    character += 1;\n                    c = source_row.charAt(0);\n                    switch (c) {\n                    case '':\n                        fail_at('missing_a', line, character, c);\n                        break;\n                    case end:\n                        source_row = source_row.slice(1);\n                        character += 1;\n                        return it('(range)', value);\n                    case xquote:\n                    case '\\\\':\n                        warn_at('unexpected_a', line, character, c);\n                        break;\n                    }\n                    value += c;\n                }\n            },\n\n// token -- this is called by advance to get the next token.\n\n            token: function () {\n                var b, c, captures, digit, depth, flag, high, i, j, length, low, quote, symbol;\n\n                function match(x) {\n                    var exec = x.exec(source_row), first;\n                    if (exec) {\n                        length = exec[0].length;\n                        first = exec[1];\n                        c = first.charAt(0);\n                        source_row = source_row.substr(length);\n                        from = character + length - first.length;\n                        character += length;\n                        return first;\n                    }\n                }\n\n                function string(x) {\n                    var c, j, r = '';\n\n                    function hex(n) {\n                        var i = parseInt(source_row.substr(j + 1, n), 16);\n                        j += n;\n                        if (i >= 32 && i <= 126 &&\n                                i !== 34 && i !== 92 && i !== 39) {\n                            warn_at('unexpected_a', line, character, '\\\\');\n                        }\n                        character += n;\n                        c = String.fromCharCode(i);\n                    }\n\n                    if (json_mode && x !== '\"') {\n                        warn_at('expected_a', line, character, '\"');\n                    }\n\n                    if (xquote === x || (xmode === 'scriptstring' && !xquote)) {\n                        return it('(punctuator)', x);\n                    }\n\n                    j = 0;\n                    for (;;) {\n                        while (j >= source_row.length) {\n                            j = 0;\n                            if (xmode !== 'html' || !next_line()) {\n                                fail_at('unclosed', line, from);\n                            }\n                        }\n                        c = source_row.charAt(j);\n                        if (c === x) {\n                            character += 1;\n                            source_row = source_row.substr(j + 1);\n                            return it('(string)', r, x);\n                        }\n                        if (c < ' ') {\n                            if (c === '\\n' || c === '\\r') {\n                                break;\n                            }\n                            warn_at('control_a',\n                                line, character + j, source_row.slice(0, j));\n                        } else if (c === xquote) {\n                            warn_at('bad_html', line, character + j);\n                        } else if (c === '<') {\n                            if (option.safe && xmode === 'html') {\n                                warn_at('adsafe_a', line, character + j, c);\n                            } else if (source_row.charAt(j + 1) === '/' && (xmode || option.safe)) {\n                                warn_at('expected_a_b', line, character,\n                                    '<\\\\/', '</');\n                            } else if (source_row.charAt(j + 1) === '!' && (xmode || option.safe)) {\n                                warn_at('unexpected_a', line, character, '<!');\n                            }\n                        } else if (c === '\\\\') {\n                            if (xmode === 'html') {\n                                if (option.safe) {\n                                    warn_at('adsafe_a', line, character + j, c);\n                                }\n                            } else if (xmode === 'styleproperty') {\n                                j += 1;\n                                character += 1;\n                                c = source_row.charAt(j);\n                                if (c !== x) {\n                                    warn_at('unexpected_a', line, character, '\\\\');\n                                }\n                            } else {\n                                j += 1;\n                                character += 1;\n                                c = source_row.charAt(j);\n                                switch (c) {\n                                case xquote:\n                                    warn_at('bad_html', line, character + j);\n                                    break;\n                                case '\\\\':\n                                case '\"':\n                                case '/':\n                                    break;\n                                case '\\'':\n                                    if (json_mode) {\n                                        warn_at('unexpected_a', line, character, '\\\\\\'');\n                                    }\n                                    break;\n                                case 'b':\n                                    c = '\\b';\n                                    break;\n                                case 'f':\n                                    c = '\\f';\n                                    break;\n                                case 'n':\n                                    c = '\\n';\n                                    break;\n                                case 'r':\n                                    c = '\\r';\n                                    break;\n                                case 't':\n                                    c = '\\t';\n                                    break;\n                                case 'u':\n                                    hex(4);\n                                    break;\n                                case 'v':\n                                    if (json_mode) {\n                                        warn_at('unexpected_a', line, character, '\\\\v');\n                                    }\n                                    c = '\\v';\n                                    break;\n                                case 'x':\n                                    if (json_mode) {\n                                        warn_at('unexpected_a', line, character, '\\\\x');\n                                    }\n                                    hex(2);\n                                    break;\n                                default:\n                                    warn_at('unexpected_a', line, character, '\\\\');\n                                }\n                            }\n                        }\n                        r += c;\n                        character += 1;\n                        j += 1;\n                    }\n                }\n\n                for (;;) {\n                    while (!source_row) {\n                        if (!next_line()) {\n                            return it('(end)');\n                        }\n                    }\n                    while (xmode === 'outer') {\n                        i = source_row.search(ox);\n                        if (i === 0) {\n                            break;\n                        } else if (i > 0) {\n                            character += 1;\n                            source_row = source_row.slice(i);\n                            break;\n                        } else {\n                            if (!next_line()) {\n                                return it('(end)', '');\n                            }\n                        }\n                    }\n                    symbol = match(rx[xmode] || tx);\n                    if (!symbol) {\n                        symbol = '';\n                        c = '';\n                        while (source_row && source_row < '!') {\n                            source_row = source_row.substr(1);\n                        }\n                        if (source_row) {\n                            if (xmode === 'html') {\n                                return it('(error)', source_row.charAt(0));\n                            } else {\n                                fail_at('unexpected_a',\n                                    line, character, source_row.substr(0, 1));\n                            }\n                        }\n                    } else {\n\n//      identifier\n\n                        if (c.isAlpha() || c === '_' || c === '$') {\n                            return it('(identifier)', symbol);\n                        }\n\n//      number\n\n                        if (c.isDigit()) {\n                            if (xmode !== 'style' &&\n                                    xmode !== 'styleproperty' &&\n                                    source_row.substr(0, 1).isAlpha()) {\n                                warn_at('expected_space_a_b',\n                                    line, character, c, source_row.charAt(0));\n                            }\n                            if (c === '0') {\n                                digit = symbol.substr(1, 1);\n                                if (digit.isDigit()) {\n                                    if (token.id !== '.' && xmode !== 'styleproperty') {\n                                        warn_at('unexpected_a',\n                                            line, character, symbol);\n                                    }\n                                } else if (json_mode && (digit === 'x' || digit === 'X')) {\n                                    warn_at('unexpected_a', line, character, '0x');\n                                }\n                            }\n                            if (symbol.substr(symbol.length - 1) === '.') {\n                                warn_at('trailing_decimal_a', line,\n                                    character, symbol);\n                            }\n                            if (xmode !== 'style') {\n                                digit = +symbol;\n                                if (!isFinite(digit)) {\n                                    warn_at('bad_number', line, character, symbol);\n                                }\n                                symbol = digit;\n                            }\n                            return it('(number)', symbol);\n                        }\n                        switch (symbol) {\n\n//      string\n\n                        case '\"':\n                        case \"'\":\n                            return string(symbol);\n\n//      // comment\n\n                        case '//':\n                            collect_comment(source_row, '//', line, character);\n                            source_row = '';\n                            break;\n\n//      /* comment\n\n                        case '/*':\n                            quote = '/*';\n                            for (;;) {\n                                i = source_row.search(lx);\n                                if (i >= 0) {\n                                    break;\n                                }\n                                collect_comment(source_row, quote, line, character);\n                                quote = '';\n                                if (!next_line()) {\n                                    fail_at('unclosed_comment', line, character);\n                                }\n                            }\n                            collect_comment(source_row.slice(0, i), quote, character, line);\n                            character += i + 2;\n                            if (source_row.substr(i, 1) === '/') {\n                                fail_at('nested_comment', line, character);\n                            }\n                            source_row = source_row.substr(i + 2);\n                            break;\n\n                        case '':\n                            break;\n//      /\n                        case '/':\n                            if (token.id === '/=') {\n                                fail_at(\n                                    bundle.slash_equal,\n                                    line,\n                                    from\n                                );\n                            }\n                            if (prereg) {\n                                depth = 0;\n                                captures = 0;\n                                length = 0;\n                                for (;;) {\n                                    b = true;\n                                    c = source_row.charAt(length);\n                                    length += 1;\n                                    switch (c) {\n                                    case '':\n                                        fail_at('unclosed_regexp', line, from);\n                                        return;\n                                    case '/':\n                                        if (depth > 0) {\n                                            warn_at('unescaped_a',\n                                                line, from + length, '/');\n                                        }\n                                        c = source_row.substr(0, length - 1);\n                                        flag = Object.create(regexp_flag);\n                                        while (flag[source_row.charAt(length)] === true) {\n                                            flag[source_row.charAt(length)] = false;\n                                            length += 1;\n                                        }\n                                        if (source_row.charAt(length).isAlpha()) {\n                                            fail_at('unexpected_a',\n                                                line, from, source_row.charAt(length));\n                                        }\n                                        character += length;\n                                        source_row = source_row.substr(length);\n                                        quote = source_row.charAt(0);\n                                        if (quote === '/' || quote === '*') {\n                                            fail_at('confusing_regexp',\n                                                line, from);\n                                        }\n                                        return it('(regexp)', c);\n                                    case '\\\\':\n                                        c = source_row.charAt(length);\n                                        if (c < ' ') {\n                                            warn_at('control_a',\n                                                line, from + length, String(c));\n                                        } else if (c === '<') {\n                                            warn_at(\n                                                bundle.unexpected_a,\n                                                line,\n                                                from + length,\n                                                '\\\\'\n                                            );\n                                        }\n                                        length += 1;\n                                        break;\n                                    case '(':\n                                        depth += 1;\n                                        b = false;\n                                        if (source_row.charAt(length) === '?') {\n                                            length += 1;\n                                            switch (source_row.charAt(length)) {\n                                            case ':':\n                                            case '=':\n                                            case '!':\n                                                length += 1;\n                                                break;\n                                            default:\n                                                warn_at(\n                                                    bundle.expected_a_b,\n                                                    line,\n                                                    from + length,\n                                                    ':',\n                                                    source_row.charAt(length)\n                                                );\n                                            }\n                                        } else {\n                                            captures += 1;\n                                        }\n                                        break;\n                                    case '|':\n                                        b = false;\n                                        break;\n                                    case ')':\n                                        if (depth === 0) {\n                                            warn_at('unescaped_a',\n                                                line, from + length, ')');\n                                        } else {\n                                            depth -= 1;\n                                        }\n                                        break;\n                                    case ' ':\n                                        j = 1;\n                                        while (source_row.charAt(length) === ' ') {\n                                            length += 1;\n                                            j += 1;\n                                        }\n                                        if (j > 1) {\n                                            warn_at('use_braces',\n                                                line, from + length, j);\n                                        }\n                                        break;\n                                    case '[':\n                                        c = source_row.charAt(length);\n                                        if (c === '^') {\n                                            length += 1;\n                                            if (option.regexp) {\n                                                warn_at('insecure_a',\n                                                    line, from + length, c);\n                                            } else if (source_row.charAt(length) === ']') {\n                                                fail_at('unescaped_a',\n                                                    line, from + length, '^');\n                                            }\n                                        }\n                                        quote = false;\n                                        if (c === ']') {\n                                            warn_at('empty_class', line,\n                                                from + length - 1);\n                                            quote = true;\n                                        }\nklass:                                  do {\n                                            c = source_row.charAt(length);\n                                            length += 1;\n                                            switch (c) {\n                                            case '[':\n                                            case '^':\n                                                warn_at('unescaped_a',\n                                                    line, from + length, c);\n                                                quote = true;\n                                                break;\n                                            case '-':\n                                                if (quote) {\n                                                    quote = false;\n                                                } else {\n                                                    warn_at('unescaped_a',\n                                                        line, from + length, '-');\n                                                    quote = true;\n                                                }\n                                                break;\n                                            case ']':\n                                                if (!quote) {\n                                                    warn_at('unescaped_a',\n                                                        line, from + length - 1, '-');\n                                                }\n                                                break klass;\n                                            case '\\\\':\n                                                c = source_row.charAt(length);\n                                                if (c < ' ') {\n                                                    warn_at(\n                                                        bundle.control_a,\n                                                        line,\n                                                        from + length,\n                                                        String(c)\n                                                    );\n                                                } else if (c === '<') {\n                                                    warn_at(\n                                                        bundle.unexpected_a,\n                                                        line,\n                                                        from + length,\n                                                        '\\\\'\n                                                    );\n                                                }\n                                                length += 1;\n                                                quote = true;\n                                                break;\n                                            case '/':\n                                                warn_at('unescaped_a',\n                                                    line, from + length - 1, '/');\n                                                quote = true;\n                                                break;\n                                            case '<':\n                                                if (xmode === 'script') {\n                                                    c = source_row.charAt(length);\n                                                    if (c === '!' || c === '/') {\n                                                        warn_at(\n                                                            bundle.html_confusion_a,\n                                                            line,\n                                                            from + length,\n                                                            c\n                                                        );\n                                                    }\n                                                }\n                                                quote = true;\n                                                break;\n                                            default:\n                                                quote = true;\n                                            }\n                                        } while (c);\n                                        break;\n                                    case '.':\n                                        if (option.regexp) {\n                                            warn_at('insecure_a', line,\n                                                from + length, c);\n                                        }\n                                        break;\n                                    case ']':\n                                    case '?':\n                                    case '{':\n                                    case '}':\n                                    case '+':\n                                    case '*':\n                                        warn_at('unescaped_a', line,\n                                            from + length, c);\n                                        break;\n                                    case '<':\n                                        if (xmode === 'script') {\n                                            c = source_row.charAt(length);\n                                            if (c === '!' || c === '/') {\n                                                warn_at(\n                                                    bundle.html_confusion_a,\n                                                    line,\n                                                    from + length,\n                                                    c\n                                                );\n                                            }\n                                        }\n                                        break;\n                                    }\n                                    if (b) {\n                                        switch (source_row.charAt(length)) {\n                                        case '?':\n                                        case '+':\n                                        case '*':\n                                            length += 1;\n                                            if (source_row.charAt(length) === '?') {\n                                                length += 1;\n                                            }\n                                            break;\n                                        case '{':\n                                            length += 1;\n                                            c = source_row.charAt(length);\n                                            if (c < '0' || c > '9') {\n                                                warn_at(\n                                                    bundle.expected_number_a,\n                                                    line,\n                                                    from + length,\n                                                    c\n                                                );\n                                            }\n                                            length += 1;\n                                            low = +c;\n                                            for (;;) {\n                                                c = source_row.charAt(length);\n                                                if (c < '0' || c > '9') {\n                                                    break;\n                                                }\n                                                length += 1;\n                                                low = +c + (low * 10);\n                                            }\n                                            high = low;\n                                            if (c === ',') {\n                                                length += 1;\n                                                high = Infinity;\n                                                c = source_row.charAt(length);\n                                                if (c >= '0' && c <= '9') {\n                                                    length += 1;\n                                                    high = +c;\n                                                    for (;;) {\n                                                        c = source_row.charAt(length);\n                                                        if (c < '0' || c > '9') {\n                                                            break;\n                                                        }\n                                                        length += 1;\n                                                        high = +c + (high * 10);\n                                                    }\n                                                }\n                                            }\n                                            if (source_row.charAt(length) !== '}') {\n                                                warn_at(\n                                                    bundle.expected_a_b,\n                                                    line,\n                                                    from + length,\n                                                    '}',\n                                                    c\n                                                );\n                                            } else {\n                                                length += 1;\n                                            }\n                                            if (source_row.charAt(length) === '?') {\n                                                length += 1;\n                                            }\n                                            if (low > high) {\n                                                warn_at(\n                                                    bundle.not_greater,\n                                                    line,\n                                                    from + length,\n                                                    low,\n                                                    high\n                                                );\n                                            }\n                                            break;\n                                        }\n                                    }\n                                }\n                                c = source_row.substr(0, length - 1);\n                                character += length;\n                                source_row = source_row.substr(length);\n                                return it('(regexp)', c);\n                            }\n                            return it('(punctuator)', symbol);\n\n//      punctuator\n\n                        case '<!--':\n                            length = line;\n                            c = character;\n                            for (;;) {\n                                i = source_row.indexOf('--');\n                                if (i >= 0) {\n                                    break;\n                                }\n                                i = source_row.indexOf('<!');\n                                if (i >= 0) {\n                                    fail_at('nested_comment',\n                                        line, character + i);\n                                }\n                                if (!next_line()) {\n                                    fail_at('unclosed_comment', length, c);\n                                }\n                            }\n                            length = source_row.indexOf('<!');\n                            if (length >= 0 && length < i) {\n                                fail_at('nested_comment',\n                                    line, character + length);\n                            }\n                            character += i;\n                            if (source_row.charAt(i + 2) !== '>') {\n                                fail_at('expected_a', line, character, '-->');\n                            }\n                            character += 3;\n                            source_row = source_row.slice(i + 3);\n                            break;\n                        case '#':\n                            if (xmode === 'html' || xmode === 'styleproperty') {\n                                for (;;) {\n                                    c = source_row.charAt(0);\n                                    if ((c < '0' || c > '9') &&\n                                            (c < 'a' || c > 'f') &&\n                                            (c < 'A' || c > 'F')) {\n                                        break;\n                                    }\n                                    character += 1;\n                                    source_row = source_row.substr(1);\n                                    symbol += c;\n                                }\n                                if (symbol.length !== 4 && symbol.length !== 7) {\n                                    warn_at('bad_color_a', line,\n                                        from + length, symbol);\n                                }\n                                return it('(color)', symbol);\n                            }\n                            return it('(punctuator)', symbol);\n\n                        default:\n                            if (xmode === 'outer' && c === '&') {\n                                character += 1;\n                                source_row = source_row.substr(1);\n                                for (;;) {\n                                    c = source_row.charAt(0);\n                                    character += 1;\n                                    source_row = source_row.substr(1);\n                                    if (c === ';') {\n                                        break;\n                                    }\n                                    if (!((c >= '0' && c <= '9') ||\n                                            (c >= 'a' && c <= 'z') ||\n                                            c === '#')) {\n                                        fail_at('bad_entity', line, from + length,\n                                            character);\n                                    }\n                                }\n                                break;\n                            }\n                            return it('(punctuator)', symbol);\n                        }\n                    }\n                }\n            }\n        };\n    }());\n\n\n    function add_label(symbol, type) {\n\n        if (option.safe && funct['(global)'] &&\n                typeof predefined[symbol] !== 'boolean') {\n            warn('adsafe_a', token, symbol);\n        } else if (symbol === 'hasOwnProperty') {\n            warn('bad_name_a', token, symbol);\n        }\n\n// Define symbol in the current function in the current scope.\n\n        if (Object.prototype.hasOwnProperty.call(funct, symbol) && !funct['(global)']) {\n            warn(funct[symbol] === true ?\n                bundle.used_before_a :\n                bundle.already_defined,\n                next_token, symbol);\n        }\n        funct[symbol] = type;\n        if (funct['(global)']) {\n            if (global[symbol] === false) {\n                warn('read_only');\n            }\n            global[symbol] = true;\n            if (Object.prototype.hasOwnProperty.call(implied, symbol)) {\n                warn('used_before_a', next_token, symbol);\n                delete implied[symbol];\n            }\n        } else {\n            scope[symbol] = funct;\n        }\n    }\n\n\n    function peek(distance) {\n\n// Peek ahead to a future token. The distance is how far ahead to look. The\n// default is the next token.\n\n        var found, slot = 0;\n\n        distance = distance || 0;\n        while (slot <= distance) {\n            found = lookahead[slot];\n            if (!found) {\n                found = lookahead[slot] = lex.token();\n            }\n            slot += 1;\n        }\n        return found;\n    }\n\n\n    function discard(it) {\n\n// The token will not be included in the parse tree, so move the comments\n// that are attached to the token to tokens that are in the tree.\n\n        it = it || token;\n        if (it.comments) {\n            var prev = it.prev;\n            while (prev.comments === null) {\n                prev = prev.prev;\n            }\n            if (prev.comments) {\n                prev.comments = prev.comments.concat(it.comments);\n            } else {\n                prev.comments = it.comments;\n            }\n        }\n        it.comments = null;\n    }\n\n\n    function advance(id, match) {\n\n// Produce the next token, also looking for programming errors.\n\n        if (indent) {\n\n// In indentation checking was requested, then inspect all of the line breakings.\n// The var statement is tricky because the names might be aligned or not. We\n// look at the first line break after the var to determine the programmer's\n// intention.\n\n            if (var_mode && next_token.line !== token.line) {\n                if ((var_mode !== indent || !next_token.edge) &&\n                        next_token.from === indent.at -\n                        (next_token.edge ? option.indent : 0)) {\n                    var dent = indent;\n                    for (;;) {\n                        dent.at -= option.indent;\n                        if (dent === var_mode) {\n                            break;\n                        }\n                        dent = dent.was;\n                    }\n                    dent.open = false;\n                }\n                var_mode = false;\n            }\n            if (indent.open) {\n\n// If the token is an edge.\n\n                if (next_token.edge) {\n                    if (next_token.edge === 'label') {\n                        expected_at(1);\n                    } else if (next_token.edge === 'case') {\n                        expected_at(indent.at - option.indent);\n                    } else if (indent.mode !== 'array' || next_token.line !== token.line) {\n                        expected_at(indent.at);\n                    }\n\n// If the token is not an edge, but is the first token on the line.\n\n                } else if (next_token.line !== token.line &&\n                        next_token.from < indent.at + (indent.mode ===\n                        'expression' ? 0 : option.indent)) {\n                    expected_at(indent.at + option.indent);\n                }\n            } else if (next_token.line !== token.line) {\n                if (next_token.edge) {\n                    expected_at(indent.at);\n                } else {\n                    indent.wrap = true;\n                    if (indent.mode === 'statement' || indent.mode === 'var') {\n                        expected_at(indent.at + option.indent);\n                    } else if (next_token.from < indent.at + (indent.mode ===\n                            'expression' ? 0 : option.indent)) {\n                        expected_at(indent.at + option.indent);\n                    }\n                }\n            }\n        }\n\n        switch (token.id) {\n        case '(number)':\n            if (next_token.id === '.') {\n                warn('trailing_decimal_a');\n            }\n            break;\n        case '-':\n            if (next_token.id === '-' || next_token.id === '--') {\n                warn('confusing_a');\n            }\n            break;\n        case '+':\n            if (next_token.id === '+' || next_token.id === '++') {\n                warn('confusing_a');\n            }\n            break;\n        }\n        if (token.arity === 'string' || token.identifier) {\n            anonname = token.value;\n        }\n\n        if (id && next_token.id !== id) {\n            if (match) {\n                warn('expected_a_b_from_c_d', next_token, id,\n                    match.id, match.line, next_token.value);\n            } else if (!next_token.identifier || next_token.value !== id) {\n                warn('expected_a_b', next_token, id, next_token.value);\n            }\n        }\n        prev_token = token;\n        token = next_token;\n        next_token = lookahead.shift() || lex.token();\n        if (token.id === '(end)') {\n            discard();\n        }\n    }\n\n\n    function directive() {\n        var command = this.id,\n            name,\n            old_comments_off = comments_off,\n            old_option_white = option.white,\n            value;\n        comments_off = true;\n        option.white = false;\n        if (lookahead.length > 0 || next_token.comments) {\n            warn('unexpected_a', this);\n        }\n        switch (command) {\n        case '/*properties':\n        case '/*members':\n            command = '/*properties';\n            if (!properties) {\n                properties = {};\n            }\n            break;\n        case '/*jslint':\n            if (option.safe) {\n                warn('adsafe_a', this);\n            }\n            break;\n        case '/*global':\n            if (option.safe) {\n                warn('adsafe_a', this);\n            }\n            break;\n        default:\n            fail('unpexpected_a', this);\n        }\nloop:   for (;;) {\n            for (;;) {\n                if (next_token.id === '*/') {\n                    break loop;\n                }\n                if (next_token.id !== ',') {\n                    break;\n                }\n                advance();\n            }\n            if (next_token.arity !== 'string' && !next_token.identifier) {\n                fail('unexpected_a', next_token);\n            }\n            name = next_token.value;\n            advance();\n            switch (command) {\n            case '/*global':\n                if (next_token.id === ':') {\n                    advance(':');\n                    switch (next_token.id) {\n                    case 'true':\n                        if (typeof scope[name] === 'object' ||\n                                global[name] === false) {\n                            fail('unexpected_a');\n                        }\n                        global[name] = true;\n                        advance('true');\n                        break;\n                    case 'false':\n                        if (typeof scope[name] === 'object') {\n                            fail('unexpected_a');\n                        }\n                        global[name] = false;\n                        advance('false');\n                        break;\n                    default:\n                        fail('unexpected_a');\n                    }\n                } else {\n                    if (typeof scope[name] === 'object') {\n                        fail('unexpected_a');\n                    }\n                    global[name] = false;\n                }\n                break;\n            case '/*jslint':\n                if (next_token.id !== ':') {\n                    fail('expected_a_b', next_token, ':', next_token.value);\n                }\n                advance(':');\n                switch (name) {\n                case 'indent':\n                    value = +next_token.value;\n                    if (typeof value !== 'number' ||\n                            !isFinite(value) || value < 0 ||\n                            Math.floor(value) !== value) {\n                        fail('expected_small_a');\n                    }\n                    if (value > 0) {\n                        old_option_white = true;\n                    }\n                    option.indent = value;\n                    break;\n                case 'maxerr':\n                    value = +next_token.value;\n                    if (typeof value !== 'number' ||\n                            !isFinite(value) ||\n                            value <= 0 ||\n                            Math.floor(value) !== value) {\n                        fail('expected_small_a', next_token);\n                    }\n                    option.maxerr = value;\n                    break;\n                case 'maxlen':\n                    value = +next_token.value;\n                    if (typeof value !== 'number' || !isFinite(value) || value < 0 ||\n                            Math.floor(value) !== value) {\n                        fail('expected_small_a');\n                    }\n                    option.maxlen = value;\n                    break;\n                case 'white':\n                    if (next_token.id === 'true') {\n                        old_option_white = true;\n                    } else if (next_token.id === 'false') {\n                        old_option_white = false;\n                    } else {\n                        fail('unexpected_a');\n                    }\n                    break;\n                default:\n                    if (next_token.id === 'true') {\n                        option[name] = true;\n                    } else if (next_token.id === 'false') {\n                        option[name] = false;\n                    } else {\n                        fail('unexpected_a');\n                    }\n                }\n                advance();\n                break;\n            case '/*properties':\n                properties[name] = true;\n                break;\n            default:\n                fail('unexpected_a');\n            }\n        }\n        if (command === '/*jslint') {\n            assume();\n        }\n        comments_off = old_comments_off;\n        advance('*/');\n        option.white = old_option_white;\n    }\n\n\n// Indentation intention\n\n    function edge(mode) {\n        next_token.edge = !indent || (indent.open && (mode || true));\n    }\n\n\n    function step_in(mode) {\n        var open, was;\n        if (typeof mode === 'number') {\n            indent = {\n                at: mode,\n                open: true,\n                was: was\n            };\n        } else if (!indent) {\n            indent = {\n                at: 1,\n                mode: 'statement',\n                open: true\n            };\n        } else {\n            was = indent;\n            open = mode === 'var' ||\n                (next_token.line !== token.line && mode !== 'statement');\n            indent = {\n                at: (open || mode === 'control' ?\n                    was.at + option.indent : was.at) +\n                    (was.wrap ? option.indent : 0),\n                mode: mode,\n                open: open,\n                was: was\n            };\n            if (mode === 'var' && open) {\n                var_mode = indent;\n            }\n        }\n    }\n\n    function step_out(id, symbol) {\n        if (id) {\n            if (indent && indent.open) {\n                indent.at -= option.indent;\n                edge();\n            }\n            advance(id, symbol);\n        }\n        if (indent) {\n            indent = indent.was;\n        }\n    }\n\n// Functions for conformance of whitespace.\n\n    function one_space(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if (right.id !== '(end)' && option.white &&\n                (token.line !== right.line ||\n                token.thru + 1 !== right.from)) {\n            warn('expected_space_a_b', right, token.value, right.value);\n        }\n    }\n\n    function one_space_only(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if (right.id !== '(end)' && (left.line !== right.line ||\n                (option.white && left.thru + 1 !== right.from))) {\n            warn('expected_space_a_b', right, left.value, right.value);\n        }\n    }\n\n    function no_space(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if ((option.white || xmode === 'styleproperty' || xmode === 'style') &&\n                left.thru !== right.from && left.line === right.line) {\n            warn('unexpected_space_a_b', right, left.value, right.value);\n        }\n    }\n\n    function no_space_only(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if (right.id !== '(end)' && (left.line !== right.line ||\n                (option.white && left.thru !== right.from))) {\n            warn('unexpected_space_a_b', right, left.value, right.value);\n        }\n    }\n\n    function spaces(left, right) {\n        if (option.white) {\n            left = left || token;\n            right = right || next_token;\n            if (left.thru === right.from && left.line === right.line) {\n                warn('missing_space_a_b', right, left.value, right.value);\n            }\n        }\n    }\n\n    function comma() {\n        if (next_token.id !== ',') {\n            warn_at('expected_a_b', token.line, token.thru, ',', next_token.value);\n        } else {\n            if (option.white) {\n                no_space_only();\n            }\n            advance(',');\n            discard();\n            spaces();\n        }\n    }\n\n\n    function semicolon() {\n        if (next_token.id !== ';') {\n            warn_at('expected_a_b', token.line, token.thru, ';', next_token.value);\n        } else {\n            if (option.white) {\n                no_space_only();\n            }\n            advance(';');\n            discard();\n            if (semicolon_coda[next_token.id] !== true) {\n                spaces();\n            }\n        }\n    }\n\n    function use_strict() {\n        if (next_token.value === 'use strict') {\n            if (strict_mode) {\n                warn('unnecessary_use');\n            }\n            edge();\n            advance();\n            semicolon();\n            strict_mode = true;\n            option.newcap = true;\n            option.undef = true;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n\n    function are_similar(a, b) {\n        if (a === b) {\n            return true;\n        }\n        if (Array.isArray(a)) {\n            if (Array.isArray(b) && a.length === b.length) {\n                var i;\n                for (i = 0; i < a.length; i += 1) {\n                    if (!are_similar(a[i], b[i])) {\n                        return false;\n                    }\n                }\n                return true;\n            }\n            return false;\n        }\n        if (Array.isArray(b)) {\n            return false;\n        }\n        if (a.arity === b.arity && a.value === b.value) {\n            switch (a.arity) {\n            case 'prefix':\n            case 'suffix':\n            case undefined:\n                return are_similar(a.first, b.first);\n            case 'infix':\n                return are_similar(a.first, b.first) &&\n                    are_similar(a.second, b.second);\n            case 'ternary':\n                return are_similar(a.first, b.first) &&\n                    are_similar(a.second, b.second) &&\n                    are_similar(a.third, b.third);\n            case 'function':\n            case 'regexp':\n                return false;\n            default:\n                return true;\n            }\n        } else {\n            if (a.id === '.' && b.id === '[' && b.arity === 'infix') {\n                return a.second.value === b.second.value && b.second.arity === 'string';\n            } else if (a.id === '[' && a.arity === 'infix' && b.id === '.') {\n                return a.second.value === b.second.value && a.second.arity === 'string';\n            }\n        }\n        return false;\n    }\n\n\n// This is the heart of JSLINT, the Pratt parser. In addition to parsing, it\n// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is\n// like .nud except that it is only used on the first token of a statement.\n// Having .fud makes it much easier to define statement-oriented languages like\n// JavaScript. I retained Pratt's nomenclature.\n\n// .nud     Null denotation\n// .fud     First null denotation\n// .led     Left denotation\n//  lbp     Left binding power\n//  rbp     Right binding power\n\n// They are elements of the parsing method called Top Down Operator Precedence.\n\n    function expression(rbp, initial) {\n\n// rbp is the right binding power.\n// initial indicates that this is the first expression of a statement.\n\n        var left;\n        if (next_token.id === '(end)') {\n            fail('unexpected_a', token, next_token.id);\n        }\n        advance();\n        if (option.safe && typeof predefined[token.value] === 'boolean' &&\n                (next_token.id !== '(' && next_token.id !== '.')) {\n            warn('adsafe', token);\n        }\n        if (initial) {\n            anonname = 'anonymous';\n            funct['(verb)'] = token.value;\n        }\n        if (initial === true && token.fud) {\n            left = token.fud();\n        } else {\n            if (token.nud) {\n                left = token.nud();\n            } else {\n                if (next_token.arity === 'number' && token.id === '.') {\n                    warn('leading_decimal_a', token,\n                        next_token.value);\n                    advance();\n                    return token;\n                } else {\n                    fail('expected_identifier_a', token, token.id);\n                }\n            }\n            while (rbp < next_token.lbp) {\n                advance();\n                if (token.led) {\n                    left = token.led(left);\n                } else {\n                    fail('expected_operator_a', token, token.id);\n                }\n            }\n        }\n        return left;\n    }\n\n\n// Functional constructors for making the symbols that will be inherited by\n// tokens.\n\n    function symbol(s, p) {\n        var x = syntax[s];\n        if (!x || typeof x !== 'object') {\n            syntax[s] = x = {\n                id: s,\n                lbp: p,\n                value: s\n            };\n        }\n        return x;\n    }\n\n\n    function delim(s) {\n        return symbol(s, 0);\n    }\n\n\n    function postscript(x) {\n        x.postscript = true;\n        return x;\n    }\n\n    function ultimate(s) {\n        var x = symbol(s, 0);\n        x.from = 1;\n        x.thru = 1;\n        x.line = 0;\n        x.edge = true;\n        s.value = s;\n        return postscript(x);\n    }\n\n\n    function stmt(s, f) {\n        var x = delim(s);\n        x.identifier = x.reserved = true;\n        x.fud = f;\n        return x;\n    }\n\n    function labeled_stmt(s, f) {\n        var x = stmt(s, f);\n        x.labeled = true;\n    }\n\n    function disrupt_stmt(s, f) {\n        var x = stmt(s, f);\n        x.disrupt = true;\n    }\n\n\n    function reserve_name(x) {\n        var c = x.id.charAt(0);\n        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {\n            x.identifier = x.reserved = true;\n        }\n        return x;\n    }\n\n\n    function prefix(s, f) {\n        var x = symbol(s, 150);\n        reserve_name(x);\n        x.nud = (typeof f === 'function') ? f : function () {\n            if (s === 'typeof') {\n                one_space();\n            } else {\n                no_space_only();\n            }\n            this.first = expression(150);\n            this.arity = 'prefix';\n            if (this.id === '++' || this.id === '--') {\n                if (option.plusplus) {\n                    warn('unexpected_a', this);\n                } else if ((!this.first.identifier || this.first.reserved) &&\n                        this.first.id !== '.' && this.first.id !== '[') {\n                    warn('bad_operand', this);\n                }\n            }\n            return this;\n        };\n        return x;\n    }\n\n\n    function type(s, arity, nud) {\n        var x = delim(s);\n        x.arity = arity;\n        if (nud) {\n            x.nud = nud;\n        }\n        return x;\n    }\n\n\n    function reserve(s, f) {\n        var x = delim(s);\n        x.identifier = x.reserved = true;\n        if (typeof f === 'function') {\n            x.nud = f;\n        }\n        return x;\n    }\n\n\n    function reservevar(s, v) {\n        return reserve(s, function () {\n            if (typeof v === 'function') {\n                v(this);\n            }\n            return this;\n        });\n    }\n\n\n    function infix(s, p, f, w) {\n        var x = symbol(s, p);\n        reserve_name(x);\n        x.led = function (left) {\n            this.arity = 'infix';\n            if (!w) {\n                spaces(prev_token, token);\n                spaces();\n            }\n            if (typeof f === 'function') {\n                return f(left, this);\n            } else {\n                this.first = left;\n                this.second = expression(p);\n                return this;\n            }\n        };\n        return x;\n    }\n\n    function expected_relation(node, message) {\n        if (node.assign) {\n            warn(message || bundle.conditional_assignment, node);\n        }\n        return node;\n    }\n\n    function expected_condition(node, message) {\n        switch (node.id) {\n        case '[':\n        case '-':\n            if (node.arity !== 'infix') {\n                warn(message || bundle.weird_condition, node);\n            }\n            break;\n        case 'false':\n        case 'function':\n        case 'Infinity':\n        case 'NaN':\n        case 'null':\n        case 'true':\n        case 'undefined':\n        case 'void':\n        case '(number)':\n        case '(regexp)':\n        case '(string)':\n        case '{':\n            warn(message || bundle.weird_condition, node);\n            break;\n        }\n        return node;\n    }\n\n    function check_relation(node) {\n        switch (node.arity) {\n        case 'prefix':\n            switch (node.id) {\n            case '{':\n            case '[':\n                warn('unexpected_a', node);\n                break;\n            case '!':\n                warn('confusing_a', node);\n                break;\n            }\n            break;\n        case 'function':\n        case 'regexp':\n            warn('unexpected_a', node);\n            break;\n        default:\n            if (node.id  === 'NaN') {\n                warn('isnan', node);\n            }\n        }\n        return node;\n    }\n\n\n    function relation(s, eqeq) {\n        var x = infix(s, 100, function (left, that) {\n            check_relation(left);\n            if (eqeq) {\n                warn('expected_a_b', that, eqeq, that.id);\n            }\n            var right = expression(100);\n            if (are_similar(left, right) ||\n                    ((left.arity === 'string' || left.arity === 'number') &&\n                    (right.arity === 'string' || right.arity === 'number'))) {\n                warn('weird_relation', that);\n            }\n            that.first = left;\n            that.second = check_relation(right);\n            return that;\n        });\n        return x;\n    }\n\n\n    function assignop(s, bit) {\n        var x = infix(s, 20, function (left, that) {\n            var l;\n            if (option.bitwise && bit) {\n                warn('unexpected_a', that);\n            }\n            that.first = left;\n            if (funct[left.value] === false) {\n                warn('read_only', left);\n            } else if (left['function']) {\n                warn('a_function', left);\n            }\n            if (option.safe) {\n                l = left;\n                do {\n                    if (typeof predefined[l.value] === 'boolean') {\n                        warn('adsafe', l);\n                    }\n                    l = l.first;\n                } while (l);\n            }\n            if (left) {\n                if (left === syntax['function']) {\n                    warn('identifier_function', token);\n                }\n                if (left.id === '.' || left.id === '[') {\n                    if (!left.first || left.first.value === 'arguments') {\n                        warn('bad_assignment', that);\n                    }\n                    that.second = expression(19);\n                    if (that.id === '=' && are_similar(that.first, that.second)) {\n                        warn('weird_assignment', that);\n                    }\n                    return that;\n                } else if (left.identifier && !left.reserved) {\n                    if (funct[left.value] === 'exception') {\n                        warn('assign_exception', left);\n                    }\n                    that.second = expression(19);\n                    if (that.id === '=' && are_similar(that.first, that.second)) {\n                        warn('weird_assignment', that);\n                    }\n                    return that;\n                }\n            }\n            fail('bad_assignment', that);\n        });\n        x.assign = true;\n        return x;\n    }\n\n\n    function bitwise(s, p) {\n        return infix(s, p, function (left, that) {\n            if (option.bitwise) {\n                warn('unexpected_a', that);\n            }\n            that.first = left;\n            that.second = expression(p);\n            return that;\n        });\n    }\n\n\n    function suffix(s, f) {\n        var x = symbol(s, 150);\n        x.led = function (left) {\n            no_space_only(prev_token, token);\n            if (option.plusplus) {\n                warn('unexpected_a', this);\n            } else if ((!left.identifier || left.reserved) &&\n                    left.id !== '.' && left.id !== '[') {\n                warn('bad_operand', this);\n            }\n            this.first = left;\n            this.arity = 'suffix';\n            return this;\n        };\n        return x;\n    }\n\n\n    function optional_identifier() {\n        if (next_token.identifier) {\n            advance();\n            if (option.safe && banned[token.value]) {\n                warn('adsafe_a', token);\n            } else if (token.reserved && !option.es5) {\n                warn('expected_identifier_a_reserved', token);\n            }\n            return token.value;\n        }\n    }\n\n\n    function identifier() {\n        var i = optional_identifier();\n        if (i) {\n            return i;\n        }\n        if (token.id === 'function' && next_token.id === '(') {\n            warn('name_function');\n        } else {\n            fail('expected_identifier_a');\n        }\n    }\n\n\n    function statement(no_indent) {\n\n// Usually a statement starts a line. Exceptions include the var statement in the\n// initialization part of a for statement, and an if after an else.\n\n        var label, old_scope = scope, the_statement;\n\n// We don't like the empty statement.\n\n        if (next_token.id === ';') {\n            warn('unexpected_a');\n            semicolon();\n            return;\n        }\n\n// Is this a labeled statement?\n\n        if (next_token.identifier && !next_token.reserved && peek().id === ':') {\n            edge('label');\n            label = next_token;\n            advance();\n            discard();\n            advance(':');\n            discard();\n            scope = Object.create(old_scope);\n            add_label(label.value, 'label');\n            if (next_token.labeled !== true) {\n                warn('label_a_b', next_token, label.value, next_token.value);\n            }\n            if (jx.test(label.value + ':')) {\n                warn('url', label);\n            }\n            next_token.label = label;\n        }\n\n// Parse the statement.\n\n        edge();\n        step_in('statement');\n        the_statement = expression(0, true);\n        if (the_statement) {\n\n// Look for the final semicolon.\n\n            if (the_statement.arity === 'statement') {\n                if (the_statement.id === 'switch' ||\n                        (the_statement.block && the_statement.id !== 'do')) {\n                    spaces();\n                } else {\n                    semicolon();\n                }\n            } else {\n\n// If this is an expression statement, determine if it is acceptble.\n// We do not like\n//      new Blah();\n// statments. If it is to be used at all, new should only be used to make\n// objects, not side effects. The expression statements we do like do\n// assignment or invocation or delete.\n\n                if (the_statement.id === '(') {\n                    if (the_statement.first.id === 'new') {\n                        warn('bad_new');\n                    }\n                } else if (!the_statement.assign &&\n                        the_statement.id !== 'delete' &&\n                        the_statement.id !== '++' &&\n                        the_statement.id !== '--') {\n                    warn('assignment_function_expression', token);\n                }\n                semicolon();\n            }\n        }\n        step_out();\n        scope = old_scope;\n        return the_statement;\n    }\n\n\n    function statements() {\n        var array = [], disruptor, the_statement;\n\n// A disrupt statement may not be followed by any other statement.\n// If the last statement is disrupt, then the sequence is disrupt.\n\n        while (next_token.postscript !== true) {\n            if (next_token.id === ';') {\n                warn('unexpected_a', next_token);\n                semicolon();\n            } else {\n                if (disruptor) {\n                    warn('unreachable_a_b', next_token, next_token.value,\n                        disruptor.value);\n                    disruptor = null;\n                }\n                the_statement = statement();\n                if (the_statement) {\n                    array.push(the_statement);\n                    if (the_statement.disrupt) {\n                        disruptor = the_statement;\n                        array.disrupt = true;\n                    }\n                }\n            }\n        }\n        return array;\n    }\n\n\n    function block(ordinary) {\n\n// array block is array sequence of statements wrapped in braces.\n// ordinary is false for function bodies and try blocks.\n// ordinary is true for if statements, while, etc.\n\n        var array,\n            curly = next_token,\n            old_inblock = in_block,\n            old_scope = scope,\n            old_strict_mode = strict_mode;\n\n        in_block = ordinary;\n        scope = Object.create(scope);\n        spaces();\n        if (next_token.id === '{') {\n            advance('{');\n            step_in();\n            if (!ordinary && !use_strict() && !old_strict_mode &&\n                    option.strict && funct['(context)']['(global)']) {\n                warn('missing_use_strict');\n            }\n            array = statements();\n            strict_mode = old_strict_mode;\n            step_out('}', curly);\n            discard();\n        } else if (!ordinary) {\n            fail('expected_a_b', next_token, '{', next_token.value);\n        } else {\n            warn('expected_a_b', next_token, '{', next_token.value);\n            array = [statement()];\n            array.disrupt = array[0].disrupt;\n        }\n        funct['(verb)'] = null;\n        scope = old_scope;\n        in_block = old_inblock;\n        if (ordinary && array.length === 0) {\n            warn('empty_block');\n        }\n        return array;\n    }\n\n\n    function tally_property(name) {\n        if (properties && typeof properties[name] !== 'boolean') {\n            warn('unexpected_member_a', token, name);\n        }\n        if (typeof member[name] === 'number') {\n            member[name] += 1;\n        } else {\n            member[name] = 1;\n        }\n    }\n\n\n    function note_implied(token) {\n        var name = token.value, line = token.line, a = implied[name];\n        if (typeof a === 'function') {\n            a = false;\n        }\n        if (!a) {\n            a = [line];\n            implied[name] = a;\n        } else if (a[a.length - 1] !== line) {\n            a.push(line);\n        }\n    }\n\n\n// ECMAScript parser\n\n    syntax['(identifier)'] = {\n        type: '(identifier)',\n        lbp: 0,\n        identifier: true,\n        nud: function () {\n            var variable = this.value,\n                site = scope[variable];\n            if (typeof site === 'function') {\n                site = undefined;\n            }\n\n// The name is in scope and defined in the current function.\n\n            if (funct === site) {\n\n//      Change 'unused' to 'var', and reject labels.\n\n                switch (funct[variable]) {\n                case 'error':\n                    warn('unexpected_a', token);\n                    funct[variable] = 'var';\n                    break;\n                case 'unused':\n                    funct[variable] = 'var';\n                    break;\n                case 'unction':\n                    funct[variable] = 'function';\n                    this['function'] = true;\n                    break;\n                case 'function':\n                    this['function'] = true;\n                    break;\n                case 'label':\n                    warn('a_label', token, variable);\n                    break;\n                }\n\n// The name is not defined in the function.  If we are in the global scope,\n// then we have an undefined variable.\n\n            } else if (funct['(global)']) {\n                if (typeof global[variable] === 'boolean') {\n                    funct[variable] = global[variable];\n                } else {\n                    if (option.undef) {\n                        warn('not_a_defined', token, variable);\n                    } else {\n                        note_implied(token);\n                    }\n                }\n\n// If the name is already defined in the current\n// function, but not as outer, then there is a scope error.\n\n            } else {\n                switch (funct[variable]) {\n                case 'closure':\n                case 'function':\n                case 'var':\n                case 'unused':\n                    warn('a_scope', token, variable);\n                    break;\n                case 'label':\n                    warn('a_label', token, variable);\n                    break;\n                case 'outer':\n                case true:\n                case false:\n                    break;\n                default:\n\n// If the name is defined in an outer function, make an outer entry, and if\n// it was unused, make it var.\n\n                    if (typeof site === 'boolean') {\n                        funct[variable] = site;\n                        functions[0][variable] = true;\n                    } else if (site === null) {\n                        warn('a_not_allowed', token, variable);\n                        note_implied(token);\n                    } else if (typeof site !== 'object') {\n                        if (option.undef) {\n                            warn('a_not_defined', token, variable);\n                        } else {\n                            funct[variable] = true;\n                        }\n                        note_implied(token);\n                    } else {\n                        switch (site[variable]) {\n                        case 'function':\n                        case 'unction':\n                            this['function'] = true;\n                            site[variable] = 'closure';\n                            funct[variable] = site['(global)'] ? false : 'outer';\n                            break;\n                        case 'var':\n                        case 'unused':\n                            site[variable] = 'closure';\n                            funct[variable] = site['(global)'] ? true : 'outer';\n                            break;\n                        case 'closure':\n                        case 'parameter':\n                            funct[variable] = site['(global)'] ? true : 'outer';\n                            break;\n                        case 'error':\n                            warn('not_a_defined', token);\n                            break;\n                        case 'label':\n                            warn('a_label', token, variable);\n                            break;\n                        }\n                    }\n                }\n            }\n            return this;\n        },\n        led: function () {\n            fail('expected_operator_a');\n        }\n    };\n\n// Build the syntax table by declaring the syntactic elements.\n\n    type('(color)', 'color');\n    type('(number)', 'number', return_this);\n    type('(string)', 'string', return_this);\n    type('(range)', 'range');\n    type('(regexp)', 'regexp', return_this);\n\n    ultimate('(begin)');\n    ultimate('(end)');\n    ultimate('(error)');\n    postscript(delim('</'));\n    delim('<!');\n    delim('<!--');\n    delim('-->');\n    postscript(delim('}'));\n    delim(')');\n    delim(']');\n    postscript(delim('\"'));\n    postscript(delim('\\''));\n    delim(';');\n    delim(':');\n    delim(',');\n    delim('#');\n    delim('@');\n    delim('*/');\n    postscript(reserve('case'));\n    reserve('catch');\n    postscript(reserve('default'));\n    reserve('else');\n    reserve('finally');\n\n    reservevar('arguments', function (x) {\n        if (strict_mode && funct['(global)']) {\n            warn('strict', x);\n        } else if (option.safe) {\n            warn('adsafe', x);\n        }\n    });\n    reservevar('eval', function (x) {\n        if (option.safe) {\n            warn('adsafe', x);\n        }\n    });\n    reservevar('false');\n    reservevar('Infinity');\n    reservevar('NaN');\n    reservevar('null');\n    reservevar('this', function (x) {\n        if (strict_mode && ((funct['(statement)'] &&\n                funct['(name)'].charAt(0) > 'Z') || funct['(global)'])) {\n            warn('strict', x);\n        } else if (option.safe) {\n            warn('adsafe', x);\n        }\n    });\n    reservevar('true');\n    reservevar('undefined');\n\n    assignop('=');\n    assignop('+=');\n    assignop('-=');\n    assignop('*=');\n    assignop('/=').nud = function () {\n        fail('slash_equal');\n    };\n    assignop('%=');\n    assignop('&=', true);\n    assignop('|=', true);\n    assignop('^=', true);\n    assignop('<<=', true);\n    assignop('>>=', true);\n    assignop('>>>=', true);\n\n    infix('?', 30, function (left, that) {\n        that.first = expected_condition(expected_relation(left));\n        that.second = expression(0);\n        spaces();\n        advance(':');\n        discard();\n        spaces();\n        that.third = expression(10);\n        that.arity = 'ternary';\n        if (are_similar(that.second, that.third)) {\n            warn('weird_ternary', that);\n        }\n        return that;\n    });\n\n    infix('||', 40, function (left, that) {\n        function paren_check(that) {\n            if (that.id === '&&' && !that.paren) {\n                warn('and', that);\n            }\n            return that;\n        }\n\n        that.first = paren_check(expected_condition(expected_relation(left)));\n        that.second = paren_check(expected_relation(expression(40)));\n        if (are_similar(that.first, that.second)) {\n            warn('weird_condition', that);\n        }\n        return that;\n    });\n\n    infix('&&', 50, function (left, that) {\n        that.first = expected_condition(expected_relation(left));\n        that.second = expected_relation(expression(50));\n        if (are_similar(that.first, that.second)) {\n            warn('weird_condition', that);\n        }\n        return that;\n    });\n\n    prefix('void', function () {\n        this.first = expression(0);\n        if (this.first.arity !== 'number' || this.first.value) {\n            warn('unexpected_a', this);\n            return this;\n        }\n        return this;\n    });\n\n    bitwise('|', 70);\n    bitwise('^', 80);\n    bitwise('&', 90);\n\n    relation('==', '===');\n    relation('===');\n    relation('!=', '!==');\n    relation('!==');\n    relation('<');\n    relation('>');\n    relation('<=');\n    relation('>=');\n\n    bitwise('<<', 120);\n    bitwise('>>', 120);\n    bitwise('>>>', 120);\n\n    infix('in', 120, function (left, that) {\n        warn('infix_in', that);\n        that.left = left;\n        that.right = expression(130);\n        return that;\n    });\n    infix('instanceof', 120);\n    infix('+', 130, function (left, that) {\n        if (!left.value) {\n            if (left.arity === 'number') {\n                warn('unexpected_a', left);\n            } else if (left.arity === 'string') {\n                warn('expected_a_b', left, 'String', '\\'\\'');\n            }\n        }\n        var right = expression(130);\n        if (!right.value) {\n            if (right.arity === 'number') {\n                warn('unexpected_a', right);\n            } else if (right.arity === 'string') {\n                warn('expected_a_b', right, 'String', '\\'\\'');\n            }\n        }\n        if (left.arity === right.arity &&\n                (left.arity === 'string' || left.arity === 'number')) {\n            left.value += right.value;\n            left.thru = right.thru;\n            if (left.arity === 'string' && jx.test(left.value)) {\n                warn('url', left);\n            }\n            discard(right);\n            discard(that);\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    });\n    prefix('+', 'num');\n    prefix('+++', function () {\n        warn('confusing_a', token);\n        this.first = expression(150);\n        this.arity = 'prefix';\n        return this;\n    });\n    infix('+++', 130, function (left) {\n        warn('confusing_a', token);\n        this.first = left;\n        this.second = expression(130);\n        return this;\n    });\n    infix('-', 130, function (left, that) {\n        if ((left.arity === 'number' && left.value === 0) || left.arity === 'string') {\n            warn('unexpected_a', left);\n        }\n        var right = expression(130);\n        if ((right.arity === 'number' && right.value === 0) || right.arity === 'string') {\n            warn('unexpected_a', left);\n        }\n        if (left.arity === right.arity && left.arity === 'number') {\n            left.value -= right.value;\n            left.thru = right.thru;\n            discard(right);\n            discard(that);\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    });\n    prefix('-');\n    prefix('---', function () {\n        warn('confusing_a', token);\n        this.first = expression(150);\n        this.arity = 'prefix';\n        return this;\n    });\n    infix('---', 130, function (left) {\n        warn('confusing_a', token);\n        this.first = left;\n        this.second = expression(130);\n        return this;\n    });\n    infix('*', 140, function (left, that) {\n        if ((left.arity === 'number' && (left.value === 0 || left.value === 1)) || left.arity === 'string') {\n            warn('unexpected_a', left);\n        }\n        var right = expression(140);\n        if ((right.arity === 'number' && (right.value === 0 || right.value === 1)) || right.arity === 'string') {\n            warn('unexpected_a', right);\n        }\n        if (left.arity === right.arity && left.arity === 'number') {\n            left.value *= right.value;\n            left.thru = right.thru;\n            discard(right);\n            discard(that);\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    });\n    infix('/', 140, function (left, that) {\n        if ((left.arity === 'number' && left.value === 0) || left.arity === 'string') {\n            warn('unexpected_a', left);\n        }\n        var right = expression(140);\n        if ((right.arity === 'number' && (right.value === 0 || right.value === 1)) || right.arity === 'string') {\n            warn('unexpected_a', right);\n        }\n        if (left.arity === right.arity && left.arity === 'number') {\n            left.value /= right.value;\n            left.thru = right.thru;\n            discard(right);\n            discard(that);\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    });\n    infix('%', 140, function (left, that) {\n        if ((left.arity === 'number' && (left.value === 0 || left.value === 1)) || left.arity === 'string') {\n            warn('unexpected_a', left);\n        }\n        var right = expression(140);\n        if ((right.arity === 'number' && (right.value === 0 || right.value === 1)) || right.arity === 'string') {\n            warn('unexpected_a', right);\n        }\n        if (left.arity === right.arity && left.arity === 'number') {\n            left.value %= right.value;\n            left.thru = right.thru;\n            discard(right);\n            discard(that);\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    });\n\n    suffix('++');\n    prefix('++');\n\n    suffix('--');\n    prefix('--');\n    prefix('delete', function () {\n        one_space();\n        var p = expression(0);\n        if (!p || (p.id !== '.' && p.id !== '[')) {\n            warn('deleted');\n        }\n        this.first = p;\n        return this;\n    });\n\n\n    prefix('~', function () {\n        no_space_only();\n        if (option.bitwise) {\n            warn('unexpected_a', this);\n        }\n        expression(150);\n        return this;\n    });\n    prefix('!', function () {\n        no_space_only();\n        this.first = expression(150);\n        this.arity = 'prefix';\n        if (bang[this.first.id] === true) {\n            warn('confusing_a', this);\n        }\n        return this;\n    });\n    prefix('typeof');\n    prefix('new', function () {\n        one_space();\n        var c = expression(160), i, p;\n        this.first = c;\n        if (c.id !== 'function') {\n            if (c.identifier) {\n                switch (c.value) {\n                case 'Object':\n                    warn('use_object', token);\n                    break;\n                case 'Array':\n                    if (next_token.id === '(') {\n                        p = next_token;\n                        p.first = this;\n                        advance('(');\n                        if (next_token.id !== ')') {\n                            p.second = expression(0);\n                            if (p.second.arity !== 'number' || !p.second.value) {\n                                expected_condition(p.second,  bundle.use_array);\n                                i = false;\n                            } else {\n                                i = true;\n                            }\n                            while (next_token.id !== ')' && next_token.id !== '(end)') {\n                                if (i) {\n                                    warn('use_array', p);\n                                    i = false;\n                                }\n                                advance();\n                            }\n                        } else {\n                            warn('use_array', token);\n                        }\n                        advance(')', p);\n                        discard();\n                        return p;\n                    }\n                    warn('use_array', token);\n                    break;\n                case 'Number':\n                case 'String':\n                case 'Boolean':\n                case 'Math':\n                case 'JSON':\n                    warn('not_a_constructor', c);\n                    break;\n                case 'Function':\n                    if (!option.evil) {\n                        warn('function_eval');\n                    }\n                    break;\n                case 'Date':\n                case 'RegExp':\n                    break;\n                default:\n                    if (c.id !== 'function') {\n                        i = c.value.substr(0, 1);\n                        if (option.newcap && (i < 'A' || i > 'Z')) {\n                            warn('constructor_name_a', token);\n                        }\n                    }\n                }\n            } else {\n                if (c.id !== '.' && c.id !== '[' && c.id !== '(') {\n                    warn('bad_constructor', token);\n                }\n            }\n        } else {\n            warn('weird_new', this);\n        }\n        if (next_token.id !== '(') {\n            warn('missing_a', next_token, '()');\n        }\n        return this;\n    });\n\n    infix('(', 160, function (left, that) {\n        if (indent && indent.mode === 'expression') {\n            no_space(prev_token, token);\n        } else {\n            no_space_only(prev_token, token);\n        }\n        if (!left.immed && left.id === 'function') {\n            warn('wrap_immediate');\n        }\n        var p = [];\n        if (left) {\n            if (left.identifier) {\n                if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {\n                    if (left.value !== 'Number' && left.value !== 'String' &&\n                            left.value !== 'Boolean' && left.value !== 'Date') {\n                        if (left.value === 'Math' || left.value === 'JSON') {\n                            warn('not_a_function', left);\n                        } else if (left.value === 'Object') {\n                            warn('use_object', token);\n                        } else if (left.value === 'Array' || option.newcap) {\n                            warn('missing_a', left, 'new');\n                        }\n                    }\n                }\n            } else if (left.id === '.') {\n                if (option.safe && left.first.value === 'Math' &&\n                        left.second === 'random') {\n                    warn('adsafe', left);\n                }\n            }\n        }\n        step_in();\n        if (next_token.id !== ')') {\n            no_space();\n            for (;;) {\n                edge();\n                p.push(expression(10));\n                if (next_token.id !== ',') {\n                    break;\n                }\n                comma();\n            }\n        }\n        no_space();\n        step_out(')', that);\n        if (typeof left === 'object') {\n            if (left.value === 'parseInt' && p.length === 1) {\n                warn('radix', left);\n            }\n            if (!option.evil) {\n                if (left.value === 'eval' || left.value === 'Function' ||\n                        left.value === 'execScript') {\n                    warn('evil', left);\n                } else if (p[0] && p[0].arity === 'string' &&\n                        (left.value === 'setTimeout' ||\n                        left.value === 'setInterval')) {\n                    warn('implied_evil', left);\n                }\n            }\n            if (!left.identifier && left.id !== '.' && left.id !== '[' &&\n                    left.id !== '(' && left.id !== '&&' && left.id !== '||' &&\n                    left.id !== '?') {\n                warn('bad_invocation', left);\n            }\n        }\n        that.first = left;\n        that.second = p;\n        return that;\n    }, true);\n\n    prefix('(', function () {\n        step_in('expression');\n        discard();\n        no_space();\n        edge();\n        if (next_token.id === 'function') {\n            next_token.immed = true;\n        }\n        var value = expression(0);\n        value.paren = true;\n        no_space();\n        step_out(')', this);\n        discard();\n        if (value.id === 'function') {\n            if (next_token.id === '(') {\n                warn('move_invocation');\n            } else {\n                warn('bad_wrap', this);\n            }\n        }\n        return value;\n    });\n\n    infix('.', 170, function (left, that) {\n        no_space(prev_token, token);\n        no_space();\n        var name = identifier();\n        if (typeof name === 'string') {\n            tally_property(name);\n        }\n        that.first = left;\n        that.second = token;\n        if (left && left.value === 'arguments' &&\n                (name === 'callee' || name === 'caller')) {\n            warn('avoid_a', left, 'arguments.' + name);\n        } else if (!option.evil && left && left.value === 'document' &&\n                (name === 'write' || name === 'writeln')) {\n            warn('write_is_wrong', left);\n        } else if (option.adsafe) {\n            if (!adsafe_top && left.value === 'ADSAFE') {\n                if (name === 'id' || name === 'lib') {\n                    warn('adsafe', that);\n                } else if (name === 'go') {\n                    if (xmode !== 'script') {\n                        warn('adsafe', that);\n                    } else if (adsafe_went || next_token.id !== '(' ||\n                            peek(0).arity !== 'string' ||\n                            peek(0).value !== adsafe_id ||\n                            peek(1).id !== ',') {\n                        fail('adsafe_a', that, 'go');\n                    }\n                    adsafe_went = true;\n                    adsafe_may = false;\n                }\n            }\n            adsafe_top = false;\n        }\n        if (!option.evil && (name === 'eval' || name === 'execScript')) {\n            warn('evil');\n        } else if (option.safe) {\n            for (;;) {\n                if (banned[name] === true) {\n                    warn('adsafe_a', token, name);\n                }\n                if (typeof predefined[left.value] !== 'boolean' ||\n                        next_token.id === '(') {\n                    break;\n                }\n                if (standard_property[name] === true) {\n                    if (next_token.id === '.') {\n                        warn('adsafe', that);\n                    }\n                    break;\n                }\n                if (next_token.id !== '.') {\n                    warn('adsafe', that);\n                    break;\n                }\n                advance('.');\n                token.first = that;\n                token.second = name;\n                that = token;\n                name = identifier();\n                if (typeof name === 'string') {\n                    tally_property(name);\n                }\n            }\n        }\n        return that;\n    }, true);\n\n    infix('[', 170, function (left, that) {\n        no_space_only(prev_token, token);\n        no_space();\n        step_in();\n        edge();\n        var e = expression(0), s;\n        if (e.arity === 'string') {\n            if (option.safe && banned[e.value] === true) {\n                warn('adsafe_a', e);\n            } else if (!option.evil &&\n                    (e.value === 'eval' || e.value === 'execScript')) {\n                warn('evil', e);\n            } else if (option.safe &&\n                    (e.value.charAt(0) === '_' || e.value.charAt(0) === '-')) {\n                warn('adsafe_subscript_a', e);\n            }\n            tally_property(e.value);\n            if (!option.sub && ix.test(e.value)) {\n                s = syntax[e.value];\n                if (!s || !s.reserved) {\n                    warn('subscript', e);\n                }\n            }\n        } else if (e.arity !== 'number' || e.value < 0) {\n            if (option.safe) {\n                warn('adsafe_subscript_a', e);\n            }\n        }\n        step_out(']', that);\n        discard();\n        no_space(prev_token, token);\n        that.first = left;\n        that.second = e;\n        return that;\n    }, true);\n\n    prefix('[', function () {\n        this.arity = 'prefix';\n        this.first = [];\n        step_in('array');\n        while (next_token.id !== '(end)') {\n            while (next_token.id === ',') {\n                warn('unexpected_a', next_token);\n                advance(',');\n                discard();\n            }\n            if (next_token.id === ']') {\n                break;\n            }\n            edge();\n            this.first.push(expression(10));\n            if (next_token.id === ',') {\n                comma();\n                if (next_token.id === ']' && !option.es5) {\n                    warn('unexpected_a', token);\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n        step_out(']', this);\n        discard();\n        return this;\n    }, 170);\n\n\n    function property_name() {\n        var id = optional_identifier(true);\n        if (!id) {\n            if (next_token.arity === 'string') {\n                id = next_token.value;\n                if (option.safe) {\n                    if (banned[id]) {\n                        warn('adsafe_a');\n                    } else if (id.charAt(0) === '_' ||\n                            id.charAt(id.length - 1) === '_') {\n                        warn('dangling_a');\n                    }\n                }\n                advance();\n            } else if (next_token.arity === 'number') {\n                id = next_token.value.toString();\n                advance();\n            }\n        }\n        return id;\n    }\n\n\n    function function_params() {\n        var id, paren = next_token, params = [];\n        advance('(');\n        step_in();\n        discard();\n        no_space();\n        if (next_token.id === ')') {\n            no_space();\n            step_out(')', paren);\n            discard();\n            return;\n        }\n        for (;;) {\n            edge();\n            id = identifier();\n            params.push(token);\n            add_label(id, 'parameter');\n            if (next_token.id === ',') {\n                comma();\n            } else {\n                no_space();\n                step_out(')', paren);\n                discard();\n                return params;\n            }\n        }\n    }\n\n\n    function do_function(func, name) {\n        var old_properties = properties,\n            old_option     = option,\n            old_global     = global,\n            old_scope      = scope;\n        funct = {\n            '(name)'     : name || '\"' + anonname + '\"',\n            '(line)'     : next_token.line,\n            '(context)'  : funct,\n            '(breakage)' : 0,\n            '(loopage)'  : 0,\n            '(scope)'    : scope,\n            '(token)'    : func\n        };\n        properties  = old_properties && Object.create(old_properties);\n        option      = Object.create(old_option);\n        global      = Object.create(old_global);\n        scope       = Object.create(old_scope);\n        token.funct = funct;\n        functions.push(funct);\n        if (name) {\n            add_label(name, 'function');\n        }\n        func.name = name || '';\n        func.first = funct['(params)'] = function_params();\n        one_space();\n        func.block = block(false);\n        funct      = funct['(context)'];\n        properties = old_properties;\n        option     = old_option;\n        global     = old_global;\n        scope      = old_scope;\n    }\n\n\n    prefix('{', function () {\n        var get, i, j, name, p, set, seen = {};\n        this.arity = 'prefix';\n        this.first = [];\n        step_in();\n        while (next_token.id !== '}') {\n\n// JSLint recognizes the ES5 extension for get/set in object literals,\n// but requires that they be used in pairs.\n\n            edge();\n            if (next_token.value === 'get' && peek().id !== ':') {\n                if (!option.es5) {\n                    warn('get_set');\n                }\n                get = next_token;\n                advance('get');\n                one_space_only();\n                name = next_token;\n                i = property_name();\n                if (!i) {\n                    fail('missing_property');\n                }\n                do_function(get, '');\n                if (funct['(loopage)']) {\n                    warn('function_loop', get);\n                }\n                p = get.first;\n                if (p) {\n                    warn('parameter_a_get_b', p[0], p[0].value, i);\n                }\n                comma();\n                set = next_token;\n                spaces();\n                edge();\n                advance('set');\n                one_space_only();\n                j = property_name();\n                if (i !== j) {\n                    fail('expected_a_b', token, i, j || next_token.value);\n                }\n                do_function(set, '');\n                p = set.first;\n                if (!p || p.length !== 1) {\n                    fail('parameter_set_a', set, 'value');\n                } else if (p[0].value !== 'value') {\n                    fail('expected_a_b', p[0], 'value', p[0].value);\n                }\n                name.first = [get, set];\n            } else {\n                name = next_token;\n                i = property_name();\n                if (typeof i !== 'string') {\n                    fail('missing_property');\n                }\n                advance(':');\n                discard();\n                spaces();\n                name.first = expression(10);\n            }\n            this.first.push(name);\n            if (seen[i] === true) {\n                warn('duplicate_a', next_token, i);\n            }\n            seen[i] = true;\n            tally_property(i);\n            if (next_token.id !== ',') {\n                break;\n            }\n            for (;;) {\n                comma();\n                if (next_token.id !== ',') {\n                    break;\n                }\n                warn('unexpected_a', next_token);\n            }\n            if (next_token.id === '}' && !option.es5) {\n                warn('unexpected_a', token);\n            }\n        }\n        step_out('}', this);\n        discard();\n        return this;\n    });\n\n    stmt('{', function () {\n        discard();\n        warn('statement_block');\n        this.arity = 'statement';\n        this.block = statements();\n        this.disrupt = this.block.disrupt;\n        advance('}', this);\n        discard();\n        return this;\n    });\n\n    stmt('/*global', directive);\n    stmt('/*jslint', directive);\n    stmt('/*members', directive);\n    stmt('/*properties', directive);\n\n    stmt('var', function () {\n\n// JavaScript does not have block scope. It only has function scope. So,\n// declaring a variable in a block can have unexpected consequences.\n\n// var.first will contain an array, the array containing name tokens\n// and assignment tokens.\n\n        var assign, id, name;\n\n        if (funct['(onevar)'] && option.onevar) {\n            warn('combine_var');\n        } else if (!funct['(global)']) {\n            funct['(onevar)'] = true;\n        }\n        this.arity = 'statement';\n        this.first = [];\n        step_in('var');\n        for (;;) {\n            name = next_token;\n            id = identifier();\n            if (funct['(global)'] && predefined[id] === false) {\n                warn('redefinition_a', token, id);\n            }\n            add_label(id, 'error');\n\n            if (next_token.id === '=') {\n                assign = next_token;\n                assign.first = name;\n                spaces();\n                advance('=');\n                spaces();\n                if (next_token.id === 'undefined') {\n                    warn('unnecessary_initialize', token, id);\n                }\n                if (peek(0).id === '=' && next_token.identifier) {\n                    fail('var_a_not');\n                }\n                assign.second = expression(0);\n                assign.arity = 'infix';\n                this.first.push(assign);\n            } else {\n                this.first.push(name);\n            }\n            funct[id] = 'unused';\n            if (next_token.id !== ',') {\n                break;\n            }\n            comma();\n            if (var_mode && next_token.line === token.line &&\n                    this.first.length === 1) {\n                var_mode = false;\n                indent.open = false;\n                indent.at -= option.indent;\n            }\n            spaces();\n            edge();\n        }\n        var_mode = false;\n        step_out();\n        return this;\n    });\n\n    stmt('function', function () {\n        one_space();\n        if (in_block) {\n            warn('function_block', token);\n        }\n        var i = identifier();\n        if (i) {\n            add_label(i, 'unction');\n            no_space();\n        }\n        do_function(this, i, true);\n        if (next_token.id === '(' && next_token.line === token.line) {\n            fail('function_statement');\n        }\n        this.arity = 'statement';\n        return this;\n    });\n\n    prefix('function', function () {\n        one_space();\n        var i = optional_identifier();\n        if (i) {\n            no_space();\n        }\n        do_function(this, i);\n        if (funct['(loopage)']) {\n            warn('function_loop');\n        }\n        this.arity = 'function';\n        return this;\n    });\n\n    stmt('if', function () {\n        var paren = next_token;\n        one_space();\n        advance('(');\n        step_in('control');\n        discard();\n        no_space();\n        edge();\n        this.arity = 'statement';\n        this.first = expected_condition(expected_relation(expression(0)));\n        no_space();\n        step_out(')', paren);\n        discard();\n        one_space();\n        this.block = block(true);\n        if (next_token.id === 'else') {\n            one_space();\n            advance('else');\n            discard();\n            one_space();\n            this['else'] = next_token.id === 'if' || next_token.id === 'switch' ?\n                statement(true) : block(true);\n            if (this['else'].disrupt && this.block.disrupt) {\n                this.disrupt = true;\n            }\n        }\n        return this;\n    });\n\n    stmt('try', function () {\n\n// try.first    The catch variable\n// try.second   The catch clause\n// try.third    The finally clause\n// try.block    The try block\n\n        var exception_variable, old_scope, paren;\n        if (option.adsafe) {\n            warn('adsafe_a', this);\n        }\n        one_space();\n        this.arity = 'statement';\n        this.block = block(false);\n        if (next_token.id === 'catch') {\n            one_space();\n            advance('catch');\n            discard();\n            one_space();\n            paren = next_token;\n            advance('(');\n            step_in('control');\n            discard();\n            no_space();\n            edge();\n            old_scope = scope;\n            scope = Object.create(old_scope);\n            exception_variable = next_token.value;\n            this.first = exception_variable;\n            if (!next_token.identifier) {\n                warn('expected_identifier_a', next_token);\n            } else {\n                add_label(exception_variable, 'exception');\n            }\n            advance();\n            no_space();\n            step_out(')', paren);\n            discard();\n            one_space();\n            this.second = block(false);\n            scope = old_scope;\n        }\n        if (next_token.id === 'finally') {\n            discard();\n            one_space();\n            advance('finally');\n            discard();\n            one_space();\n            this.third = block(false);\n        } else if (!this.second) {\n            fail('expected_a_b', next_token, 'catch', next_token.value);\n        }\n        return this;\n    });\n\n    labeled_stmt('while', function () {\n        one_space();\n        var paren = next_token;\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        advance('(');\n        step_in('control');\n        discard();\n        no_space();\n        edge();\n        this.arity = 'statement';\n        this.first = expected_relation(expression(0));\n        if (this.first.id !== 'true') {\n            expected_condition(this.first, bundle.unexpected_a);\n        }\n        no_space();\n        step_out(')', paren);\n        discard();\n        one_space();\n        this.block = block(true);\n        if (this.block.disrupt) {\n            warn('strange_loop', prev_token);\n        }\n        funct['(breakage)'] -= 1;\n        funct['(loopage)'] -= 1;\n        return this;\n    });\n\n    reserve('with');\n\n    labeled_stmt('switch', function () {\n\n// switch.first             the switch expression\n// switch.second            the array of cases. A case is 'case' or 'default' token:\n//    case.first            the array of case expressions\n//    case.second           the array of statements\n// If all of the arrays of statements are disrupt, then the switch is disrupt.\n\n        var particular,\n            the_case = next_token,\n            unbroken = true;\n        funct['(breakage)'] += 1;\n        one_space();\n        advance('(');\n        discard();\n        no_space();\n        step_in();\n        this.arity = 'statement';\n        this.first = expected_condition(expected_relation(expression(0)));\n        no_space();\n        step_out(')', the_case);\n        discard();\n        one_space();\n        advance('{');\n        step_in();\n        this.second = [];\n        while (next_token.id === 'case') {\n            the_case = next_token;\n            the_case.first = [];\n            spaces();\n            edge('case');\n            advance('case');\n            for (;;) {\n                one_space();\n                particular = expression(0);\n                the_case.first.push(particular);\n                if (particular.id === 'NaN') {\n                    warn('unexpected_a', particular);\n                }\n                no_space_only();\n                advance(':');\n                discard();\n                if (next_token.id !== 'case') {\n                    break;\n                }\n                spaces();\n                edge('case');\n                advance('case');\n                discard();\n            }\n            spaces();\n            the_case.second = statements();\n            if (the_case.second && the_case.second.length > 0) {\n                particular = the_case.second[the_case.second.length - 1];\n                if (particular.disrupt) {\n                    if (particular.id === 'break') {\n                        unbroken = false;\n                    }\n                } else {\n                    warn('missing_a_after_b', next_token, 'break', 'case');\n                }\n            } else {\n                warn('empty_case');\n            }\n            this.second.push(the_case);\n        }\n        if (this.second.length === 0) {\n            warn('missing_a', next_token, 'case');\n        }\n        if (next_token.id === 'default') {\n            spaces();\n            the_case = next_token;\n            edge('case');\n            advance('default');\n            discard();\n            no_space_only();\n            advance(':');\n            discard();\n            spaces();\n            the_case.second = statements();\n            if (the_case.second && the_case.second.length > 0) {\n                particular = the_case.second[the_case.second.length - 1];\n                if (unbroken && particular.disrupt && particular.id !== 'break') {\n                    this.disrupt = true;\n                }\n            }\n            this.second.push(the_case);\n        }\n        funct['(breakage)'] -= 1;\n        spaces();\n        step_out('}', this);\n        return this;\n    });\n\n    stmt('debugger', function () {\n        if (!option.debug) {\n            warn('unexpected_a', this);\n        }\n        this.arity = 'statement';\n        return this;\n    });\n\n    labeled_stmt('do', function () {\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        one_space();\n        this.arity = 'statement';\n        this.block = block(true);\n        if (this.block.disrupt) {\n            warn('strange_loop', prev_token);\n        }\n        one_space();\n        advance('while');\n        discard();\n        var paren = next_token;\n        one_space();\n        advance('(');\n        step_in();\n        discard();\n        no_space();\n        edge();\n        this.first = expected_condition(expected_relation(expression(0)), bundle.unexpected_a);\n        no_space();\n        step_out(')', paren);\n        discard();\n        funct['(breakage)'] -= 1;\n        funct['(loopage)'] -= 1;\n        return this;\n    });\n\n    labeled_stmt('for', function () {\n        var blok, filter, ok = false, paren = next_token, the_in, value;\n        this.arity = 'statement';\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        advance('(');\n        step_in('control');\n        discard();\n        spaces(this, paren);\n        no_space();\n        if (next_token.id === 'var') {\n            fail('move_var');\n        }\n        edge();\n        if (peek(0).id === 'in') {\n            value = next_token;\n            switch (funct[value.value]) {\n            case 'unused':\n                funct[value.value] = 'var';\n                break;\n            case 'var':\n                break;\n            default:\n                warn('bad_in_a', value);\n            }\n            advance();\n            the_in = next_token;\n            advance('in');\n            the_in.first = value;\n            the_in.second = expression(20);\n            step_out(')', paren);\n            discard();\n            this.first = the_in;\n            blok = block(true);\n            if (!option.forin) {\n                if (blok.length === 1 && typeof blok[0] === 'object' &&\n                        blok[0].value === 'if' && !blok[0]['else']) {\n                    filter = blok[0].first;\n                    while (filter.id === '&&') {\n                        filter = filter.first;\n                    }\n                    switch (filter.id) {\n                    case '===':\n                    case '!==':\n                        ok = filter.first.id === '[' ? (\n                            filter.first.first.value === the_in.second.value &&\n                            filter.first.second.value === the_in.first.value\n                        ) : (\n                            filter.first.id === 'typeof' &&\n                            filter.first.first.id === '[' &&\n                            filter.first.first.first.value === the_in.second.value &&\n                            filter.first.first.second.value === the_in.first.value\n                        );\n                        break;\n                    case '(':\n                        ok = filter.first.id === '.' && ((\n                            filter.first.first.value === the_in.second.value &&\n                            filter.first.second.value === 'hasOwnProperty' &&\n                            filter.second[0].value === the_in.first.value\n                        ) || (\n                            filter.first.first.value === 'ADSAFE' &&\n                            filter.first.second.value === 'has' &&\n                            filter.second[0].value === the_in.second.value &&\n                            filter.second[1].value === the_in.first.value\n                        ) || (\n                            filter.first.first.id === '.' &&\n                            filter.first.first.first.id === '.' &&\n                            filter.first.first.first.first.value === 'Object' &&\n                            filter.first.first.first.second.value === 'prototype' &&\n                            filter.first.first.second.value === 'hasOwnProperty' &&\n                            filter.first.second.value === 'call' &&\n                            filter.second[0].value === the_in.second.value &&\n                            filter.second[1].value === the_in.first.value\n                        ));\n                        break;\n                    }\n                }\n                if (!ok) {\n                    warn('for_if', this);\n                }\n            }\n        } else {\n            if (next_token.id !== ';') {\n                edge();\n                this.first = [];\n                for (;;) {\n                    this.first.push(expression(0, 'for'));\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    comma();\n                }\n            }\n            semicolon();\n            if (next_token.id !== ';') {\n                edge();\n                this.second = expected_relation(expression(0));\n                if (this.second.id !== 'true') {\n                    expected_condition(this.second, bundle.unexpected_a);\n                }\n            }\n            semicolon(token);\n            if (next_token.id === ';') {\n                fail('expected_a_b', next_token, ')', ';');\n            }\n            if (next_token.id !== ')') {\n                this.third = [];\n                edge();\n                for (;;) {\n                    this.third.push(expression(0, 'for'));\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    comma();\n                }\n            }\n            no_space();\n            step_out(')', paren);\n            discard();\n            one_space();\n            blok = block(true);\n        }\n        if (blok.disrupt) {\n            warn('strange_loop', prev_token);\n        }\n        this.block = blok;\n        funct['(breakage)'] -= 1;\n        funct['(loopage)'] -= 1;\n        return this;\n    });\n\n    disrupt_stmt('break', function () {\n        var label = next_token.value;\n        this.arity = 'statement';\n        if (funct['(breakage)'] === 0) {\n            warn('unexpected_a', this);\n        }\n        if (next_token.identifier && token.line === next_token.line) {\n            one_space_only();\n            if (funct[label] !== 'label') {\n                warn('not_a_label', next_token);\n            } else if (scope[label] !== funct) {\n                warn('not_a_scope', next_token);\n            }\n            this.first = next_token;\n            advance();\n        }\n        return this;\n    });\n\n    disrupt_stmt('continue', function () {\n        if (!option['continue']) {\n            warn('unexpected_a', this);\n        }\n        var label = next_token.value;\n        this.arity = 'statement';\n        if (funct['(breakage)'] === 0) {\n            warn('unexpected_a', this);\n        }\n        if (next_token.identifier && token.line === next_token.line) {\n            one_space_only();\n            if (funct[label] !== 'label') {\n                warn('not_a_label', next_token);\n            } else if (scope[label] !== funct) {\n                warn('not_a_scope', next_token);\n            }\n            this.first = next_token;\n            advance();\n        }\n        return this;\n    });\n\n    disrupt_stmt('return', function () {\n        this.arity = 'statement';\n        if (next_token.id !== ';' && next_token.line === token.line) {\n            one_space_only();\n            if (next_token.id === '/' || next_token.id === '(regexp)') {\n                warn('wrap_regexp');\n            }\n            this.first = expression(20);\n        }\n        return this;\n    });\n\n    disrupt_stmt('throw', function () {\n        this.arity = 'statement';\n        one_space_only();\n        this.first = expression(20);\n        return this;\n    });\n\n\n//  Superfluous reserved words\n\n    reserve('class');\n    reserve('const');\n    reserve('enum');\n    reserve('export');\n    reserve('extends');\n    reserve('import');\n    reserve('super');\n\n// Harmony reserved words\n\n    reserve('let');\n    reserve('yield');\n    reserve('implements');\n    reserve('interface');\n    reserve('package');\n    reserve('private');\n    reserve('protected');\n    reserve('public');\n    reserve('static');\n\n\n// Parse JSON\n\n    function json_value() {\n\n        function json_object() {\n            var brace = next_token, object = {};\n            advance('{');\n            if (next_token.id !== '}') {\n                while (next_token.id !== '(end)') {\n                    while (next_token.id === ',') {\n                        warn('unexpected_a', next_token);\n                        comma();\n                    }\n                    if (next_token.arity !== 'string') {\n                        warn('expected_string_a');\n                    }\n                    if (object[next_token.value] === true) {\n                        warn('duplicate_a');\n                    } else if (next_token.value === '__proto__') {\n                        warn('dangling_a');\n                    } else {\n                        object[next_token.value] = true;\n                    }\n                    advance();\n                    advance(':');\n                    json_value();\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    comma();\n                    if (next_token.id === '}') {\n                        warn('unexpected_a', token);\n                        break;\n                    }\n                }\n            }\n            advance('}', brace);\n        }\n\n        function json_array() {\n            var bracket = next_token;\n            advance('[');\n            if (next_token.id !== ']') {\n                while (next_token.id !== '(end)') {\n                    while (next_token.id === ',') {\n                        warn('unexpected_a', next_token);\n                        comma();\n                    }\n                    json_value();\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    comma();\n                    if (next_token.id === ']') {\n                        warn('unexpected_a', token);\n                        break;\n                    }\n                }\n            }\n            advance(']', bracket);\n        }\n\n        switch (next_token.id) {\n        case '{':\n            json_object();\n            break;\n        case '[':\n            json_array();\n            break;\n        case 'true':\n        case 'false':\n        case 'null':\n        case '(number)':\n        case '(string)':\n            advance();\n            break;\n        case '-':\n            advance('-');\n            no_space_only();\n            advance('(number)');\n            break;\n        default:\n            fail('unexpected_a');\n        }\n    }\n\n\n// CSS parsing.\n\n    function css_name() {\n        if (next_token.identifier) {\n            advance();\n            return true;\n        }\n    }\n\n\n    function css_number() {\n        if (next_token.id === '-') {\n            advance('-');\n            no_space_only();\n        }\n        if (next_token.arity === 'number') {\n            advance('(number)');\n            return true;\n        }\n    }\n\n\n    function css_string() {\n        if (next_token.arity === 'string') {\n            advance();\n            return true;\n        }\n    }\n\n    function css_color() {\n        var i, number, paren, value;\n        if (next_token.identifier) {\n            value = next_token.value;\n            if (value === 'rgb' || value === 'rgba') {\n                advance();\n                paren = next_token;\n                advance('(');\n                for (i = 0; i < 3; i += 1) {\n                    if (i) {\n                        comma();\n                    }\n                    number = next_token.value;\n                    if (next_token.arity !== 'number' || number < 0) {\n                        warn('expected_positive_a', next_token);\n                        advance();\n                    } else {\n                        advance();\n                        if (next_token.id === '%') {\n                            advance('%');\n                            if (number > 100) {\n                                warn('expected_percent_a', token, number);\n                            }\n                        } else {\n                            if (number > 255) {\n                                warn('expected_small_a', token, number);\n                            }\n                        }\n                    }\n                }\n                if (value === 'rgba') {\n                    comma();\n                    number = +next_token.value;\n                    if (next_token.arity !== 'number' || number < 0 || number > 1) {\n                        warn('expected_fraction_a', next_token);\n                    }\n                    advance();\n                    if (next_token.id === '%') {\n                        warn('unexpected_a');\n                        advance('%');\n                    }\n                }\n                advance(')', paren);\n                return true;\n            } else if (css_colorData[next_token.value] === true) {\n                advance();\n                return true;\n            }\n        } else if (next_token.id === '(color)') {\n            advance();\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_length() {\n        if (next_token.id === '-') {\n            advance('-');\n            no_space_only();\n        }\n        if (next_token.arity === 'number') {\n            advance();\n            if (next_token.arity !== 'string' &&\n                    css_lengthData[next_token.value] === true) {\n                no_space_only();\n                advance();\n            } else if (+token.value !== 0) {\n                warn('expected_linear_a');\n            }\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_line_height() {\n        if (next_token.id === '-') {\n            advance('-');\n            no_space_only();\n        }\n        if (next_token.arity === 'number') {\n            advance();\n            if (next_token.arity !== 'string' &&\n                    css_lengthData[next_token.value] === true) {\n                no_space_only();\n                advance();\n            }\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_width() {\n        if (next_token.identifier) {\n            switch (next_token.value) {\n            case 'thin':\n            case 'medium':\n            case 'thick':\n                advance();\n                return true;\n            }\n        } else {\n            return css_length();\n        }\n    }\n\n\n    function css_margin() {\n        if (next_token.identifier) {\n            if (next_token.value === 'auto') {\n                advance();\n                return true;\n            }\n        } else {\n            return css_length();\n        }\n    }\n\n    function css_attr() {\n        if (next_token.identifier && next_token.value === 'attr') {\n            advance();\n            advance('(');\n            if (!next_token.identifier) {\n                warn('expected_name_a');\n            }\n            advance();\n            advance(')');\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_comma_list() {\n        while (next_token.id !== ';') {\n            if (!css_name() && !css_string()) {\n                warn('expected_name_a');\n            }\n            if (next_token.id !== ',') {\n                return true;\n            }\n            comma();\n        }\n    }\n\n\n    function css_counter() {\n        if (next_token.identifier && next_token.value === 'counter') {\n            advance();\n            advance('(');\n            advance();\n            if (next_token.id === ',') {\n                comma();\n                if (next_token.arity !== 'string') {\n                    warn('expected_string_a');\n                }\n                advance();\n            }\n            advance(')');\n            return true;\n        }\n        if (next_token.identifier && next_token.value === 'counters') {\n            advance();\n            advance('(');\n            if (!next_token.identifier) {\n                warn('expected_name_a');\n            }\n            advance();\n            if (next_token.id === ',') {\n                comma();\n                if (next_token.arity !== 'string') {\n                    warn('expected_string_a');\n                }\n                advance();\n            }\n            if (next_token.id === ',') {\n                comma();\n                if (next_token.arity !== 'string') {\n                    warn('expected_string_a');\n                }\n                advance();\n            }\n            advance(')');\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_shape() {\n        var i;\n        if (next_token.identifier && next_token.value === 'rect') {\n            advance();\n            advance('(');\n            for (i = 0; i < 4; i += 1) {\n                if (!css_length()) {\n                    warn('expected_number_a');\n                    break;\n                }\n            }\n            advance(')');\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_url() {\n        var c, url;\n        if (next_token.identifier && next_token.value === 'url') {\n            next_token = lex.range('(', ')');\n            url = next_token.value;\n            c = url.charAt(0);\n            if (c === '\"' || c === '\\'') {\n                if (url.slice(-1) !== c) {\n                    warn('bad_url');\n                } else {\n                    url = url.slice(1, -1);\n                    if (url.indexOf(c) >= 0) {\n                        warn('bad_url');\n                    }\n                }\n            }\n            if (!url) {\n                warn('missing_url');\n            }\n            if (option.safe && ux.test(url)) {\n                fail('adsafe_a', next_token, url);\n            }\n            urls.push(url);\n            advance();\n            return true;\n        }\n        return false;\n    }\n\n\n    css_any = [css_url, function () {\n        for (;;) {\n            if (next_token.identifier) {\n                switch (next_token.value.toLowerCase()) {\n                case 'url':\n                    css_url();\n                    break;\n                case 'expression':\n                    warn('unexpected_a');\n                    advance();\n                    break;\n                default:\n                    advance();\n                }\n            } else {\n                if (next_token.id === ';' || next_token.id === '!'  ||\n                        next_token.id === '(end)' || next_token.id === '}') {\n                    return true;\n                }\n                advance();\n            }\n        }\n    }];\n\n\n    css_border_style = [\n        'none', 'dashed', 'dotted', 'double', 'groove',\n        'hidden', 'inset', 'outset', 'ridge', 'solid'\n    ];\n\n    css_break = [\n        'auto', 'always', 'avoid', 'left', 'right'\n    ];\n\n    css_media = {\n        'all': true,\n        'braille': true,\n        'embossed': true,\n        'handheld': true,\n        'print': true,\n        'projection': true,\n        'screen': true,\n        'speech': true,\n        'tty': true,\n        'tv': true\n    };\n\n    css_overflow = [\n        'auto', 'hidden', 'scroll', 'visible'\n    ];\n\n    css_attribute_data = {\n        background: [\n            true, 'background-attachment', 'background-color',\n            'background-image', 'background-position', 'background-repeat'\n        ],\n        'background-attachment': ['scroll', 'fixed'],\n        'background-color': ['transparent', css_color],\n        'background-image': ['none', css_url],\n        'background-position': [\n            2, [css_length, 'top', 'bottom', 'left', 'right', 'center']\n        ],\n        'background-repeat': [\n            'repeat', 'repeat-x', 'repeat-y', 'no-repeat'\n        ],\n        'border': [true, 'border-color', 'border-style', 'border-width'],\n        'border-bottom': [\n            true, 'border-bottom-color', 'border-bottom-style',\n            'border-bottom-width'\n        ],\n        'border-bottom-color': css_color,\n        'border-bottom-style': css_border_style,\n        'border-bottom-width': css_width,\n        'border-collapse': ['collapse', 'separate'],\n        'border-color': ['transparent', 4, css_color],\n        'border-left': [\n            true, 'border-left-color', 'border-left-style', 'border-left-width'\n        ],\n        'border-left-color': css_color,\n        'border-left-style': css_border_style,\n        'border-left-width': css_width,\n        'border-right': [\n            true, 'border-right-color', 'border-right-style',\n            'border-right-width'\n        ],\n        'border-right-color': css_color,\n        'border-right-style': css_border_style,\n        'border-right-width': css_width,\n        'border-spacing': [2, css_length],\n        'border-style': [4, css_border_style],\n        'border-top': [\n            true, 'border-top-color', 'border-top-style', 'border-top-width'\n        ],\n        'border-top-color': css_color,\n        'border-top-style': css_border_style,\n        'border-top-width': css_width,\n        'border-width': [4, css_width],\n        bottom: [css_length, 'auto'],\n        'caption-side' : ['bottom', 'left', 'right', 'top'],\n        clear: ['both', 'left', 'none', 'right'],\n        clip: [css_shape, 'auto'],\n        color: css_color,\n        content: [\n            'open-quote', 'close-quote', 'no-open-quote', 'no-close-quote',\n            css_string, css_url, css_counter, css_attr\n        ],\n        'counter-increment': [\n            css_name, 'none'\n        ],\n        'counter-reset': [\n            css_name, 'none'\n        ],\n        cursor: [\n            css_url, 'auto', 'crosshair', 'default', 'e-resize', 'help', 'move',\n            'n-resize', 'ne-resize', 'nw-resize', 'pointer', 's-resize',\n            'se-resize', 'sw-resize', 'w-resize', 'text', 'wait'\n        ],\n        direction: ['ltr', 'rtl'],\n        display: [\n            'block', 'compact', 'inline', 'inline-block', 'inline-table',\n            'list-item', 'marker', 'none', 'run-in', 'table', 'table-caption',\n            'table-cell', 'table-column', 'table-column-group',\n            'table-footer-group', 'table-header-group', 'table-row',\n            'table-row-group'\n        ],\n        'empty-cells': ['show', 'hide'],\n        'float': ['left', 'none', 'right'],\n        font: [\n            'caption', 'icon', 'menu', 'message-box', 'small-caption',\n            'status-bar', true, 'font-size', 'font-style', 'font-weight',\n            'font-family'\n        ],\n        'font-family': css_comma_list,\n        'font-size': [\n            'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large',\n            'xx-large', 'larger', 'smaller', css_length\n        ],\n        'font-size-adjust': ['none', css_number],\n        'font-stretch': [\n            'normal', 'wider', 'narrower', 'ultra-condensed',\n            'extra-condensed', 'condensed', 'semi-condensed',\n            'semi-expanded', 'expanded', 'extra-expanded'\n        ],\n        'font-style': [\n            'normal', 'italic', 'oblique'\n        ],\n        'font-variant': [\n            'normal', 'small-caps'\n        ],\n        'font-weight': [\n            'normal', 'bold', 'bolder', 'lighter', css_number\n        ],\n        height: [css_length, 'auto'],\n        left: [css_length, 'auto'],\n        'letter-spacing': ['normal', css_length],\n        'line-height': ['normal', css_line_height],\n        'list-style': [\n            true, 'list-style-image', 'list-style-position', 'list-style-type'\n        ],\n        'list-style-image': ['none', css_url],\n        'list-style-position': ['inside', 'outside'],\n        'list-style-type': [\n            'circle', 'disc', 'square', 'decimal', 'decimal-leading-zero',\n            'lower-roman', 'upper-roman', 'lower-greek', 'lower-alpha',\n            'lower-latin', 'upper-alpha', 'upper-latin', 'hebrew', 'katakana',\n            'hiragana-iroha', 'katakana-oroha', 'none'\n        ],\n        margin: [4, css_margin],\n        'margin-bottom': css_margin,\n        'margin-left': css_margin,\n        'margin-right': css_margin,\n        'margin-top': css_margin,\n        'marker-offset': [css_length, 'auto'],\n        'max-height': [css_length, 'none'],\n        'max-width': [css_length, 'none'],\n        'min-height': css_length,\n        'min-width': css_length,\n        opacity: css_number,\n        outline: [true, 'outline-color', 'outline-style', 'outline-width'],\n        'outline-color': ['invert', css_color],\n        'outline-style': [\n            'dashed', 'dotted', 'double', 'groove', 'inset', 'none',\n            'outset', 'ridge', 'solid'\n        ],\n        'outline-width': css_width,\n        overflow: css_overflow,\n        'overflow-x': css_overflow,\n        'overflow-y': css_overflow,\n        padding: [4, css_length],\n        'padding-bottom': css_length,\n        'padding-left': css_length,\n        'padding-right': css_length,\n        'padding-top': css_length,\n        'page-break-after': css_break,\n        'page-break-before': css_break,\n        position: ['absolute', 'fixed', 'relative', 'static'],\n        quotes: [8, css_string],\n        right: [css_length, 'auto'],\n        'table-layout': ['auto', 'fixed'],\n        'text-align': ['center', 'justify', 'left', 'right'],\n        'text-decoration': [\n            'none', 'underline', 'overline', 'line-through', 'blink'\n        ],\n        'text-indent': css_length,\n        'text-shadow': ['none', 4, [css_color, css_length]],\n        'text-transform': ['capitalize', 'uppercase', 'lowercase', 'none'],\n        top: [css_length, 'auto'],\n        'unicode-bidi': ['normal', 'embed', 'bidi-override'],\n        'vertical-align': [\n            'baseline', 'bottom', 'sub', 'super', 'top', 'text-top', 'middle',\n            'text-bottom', css_length\n        ],\n        visibility: ['visible', 'hidden', 'collapse'],\n        'white-space': [\n            'normal', 'nowrap', 'pre', 'pre-line', 'pre-wrap', 'inherit'\n        ],\n        width: [css_length, 'auto'],\n        'word-spacing': ['normal', css_length],\n        'word-wrap': ['break-word', 'normal'],\n        'z-index': ['auto', css_number]\n    };\n\n    function style_attribute() {\n        var v;\n        while (next_token.id === '*' || next_token.id === '#' ||\n                next_token.value === '_') {\n            if (!option.css) {\n                warn('unexpected_a');\n            }\n            advance();\n        }\n        if (next_token.id === '-') {\n            if (!option.css) {\n                warn('unexpected_a');\n            }\n            advance('-');\n            if (!next_token.identifier) {\n                warn('expected_nonstandard_style_attribute');\n            }\n            advance();\n            return css_any;\n        } else {\n            if (!next_token.identifier) {\n                warn('expected_style_attribute');\n            } else {\n                if (Object.prototype.hasOwnProperty.call(css_attribute_data, next_token.value)) {\n                    v = css_attribute_data[next_token.value];\n                } else {\n                    v = css_any;\n                    if (!option.css) {\n                        warn('unrecognized_style_attribute_a');\n                    }\n                }\n            }\n            advance();\n            return v;\n        }\n    }\n\n\n    function style_value(v) {\n        var i = 0,\n            n,\n            once,\n            match,\n            round,\n            start = 0,\n            vi;\n        switch (typeof v) {\n        case 'function':\n            return v();\n        case 'string':\n            if (next_token.identifier && next_token.value === v) {\n                advance();\n                return true;\n            }\n            return false;\n        }\n        for (;;) {\n            if (i >= v.length) {\n                return false;\n            }\n            vi = v[i];\n            i += 1;\n            if (vi === true) {\n                break;\n            } else if (typeof vi === 'number') {\n                n = vi;\n                vi = v[i];\n                i += 1;\n            } else {\n                n = 1;\n            }\n            match = false;\n            while (n > 0) {\n                if (style_value(vi)) {\n                    match = true;\n                    n -= 1;\n                } else {\n                    break;\n                }\n            }\n            if (match) {\n                return true;\n            }\n        }\n        start = i;\n        once = [];\n        for (;;) {\n            round = false;\n            for (i = start; i < v.length; i += 1) {\n                if (!once[i]) {\n                    if (style_value(css_attribute_data[v[i]])) {\n                        match = true;\n                        round = true;\n                        once[i] = true;\n                        break;\n                    }\n                }\n            }\n            if (!round) {\n                return match;\n            }\n        }\n    }\n\n    function style_child() {\n        if (next_token.arity === 'number') {\n            advance();\n            if (next_token.value === 'n' && next_token.identifier) {\n                no_space_only();\n                advance();\n                if (next_token.id === '+') {\n                    no_space_only();\n                    advance('+');\n                    no_space_only();\n                    advance('(number)');\n                }\n            }\n            return;\n        } else {\n            if (next_token.identifier &&\n                    (next_token.value === 'odd' || next_token.value === 'even')) {\n                advance();\n                return;\n            }\n        }\n        warn('unexpected_a');\n    }\n\n    function substyle() {\n        var v;\n        for (;;) {\n            if (next_token.id === '}' || next_token.id === '(end)' ||\n                    (xquote && next_token.id === xquote)) {\n                return;\n            }\n            while (next_token.id === ';') {\n                warn('unexpected_a');\n                semicolon();\n            }\n            v = style_attribute();\n            advance(':');\n            if (next_token.identifier && next_token.value === 'inherit') {\n                advance();\n            } else {\n                if (!style_value(v)) {\n                    warn('unexpected_a');\n                    advance();\n                }\n            }\n            if (next_token.id === '!') {\n                advance('!');\n                no_space_only();\n                if (next_token.identifier && next_token.value === 'important') {\n                    advance();\n                } else {\n                    warn('expected_a_b',\n                        next_token, 'important', next_token.value);\n                }\n            }\n            if (next_token.id === '}' || next_token.id === xquote) {\n                warn('expected_a_b', next_token, ';', next_token.value);\n            } else {\n                semicolon();\n            }\n        }\n    }\n\n    function style_selector() {\n        if (next_token.identifier) {\n            if (!Object.prototype.hasOwnProperty.call(html_tag, option.cap ?\n                    next_token.value.toLowerCase() : next_token.value)) {\n                warn('expected_tagname_a');\n            }\n            advance();\n        } else {\n            switch (next_token.id) {\n            case '>':\n            case '+':\n                advance();\n                style_selector();\n                break;\n            case ':':\n                advance(':');\n                switch (next_token.value) {\n                case 'active':\n                case 'after':\n                case 'before':\n                case 'checked':\n                case 'disabled':\n                case 'empty':\n                case 'enabled':\n                case 'first-child':\n                case 'first-letter':\n                case 'first-line':\n                case 'first-of-type':\n                case 'focus':\n                case 'hover':\n                case 'last-child':\n                case 'last-of-type':\n                case 'link':\n                case 'only-of-type':\n                case 'root':\n                case 'target':\n                case 'visited':\n                    advance();\n                    break;\n                case 'lang':\n                    advance();\n                    advance('(');\n                    if (!next_token.identifier) {\n                        warn('expected_lang_a');\n                    }\n                    advance(')');\n                    break;\n                case 'nth-child':\n                case 'nth-last-child':\n                case 'nth-last-of-type':\n                case 'nth-of-type':\n                    advance();\n                    advance('(');\n                    style_child();\n                    advance(')');\n                    break;\n                case 'not':\n                    advance();\n                    advance('(');\n                    if (next_token.id === ':' && peek(0).value === 'not') {\n                        warn('not');\n                    }\n                    style_selector();\n                    advance(')');\n                    break;\n                default:\n                    warn('expected_pseudo_a');\n                }\n                break;\n            case '#':\n                advance('#');\n                if (!next_token.identifier) {\n                    warn('expected_id_a');\n                }\n                advance();\n                break;\n            case '*':\n                advance('*');\n                break;\n            case '.':\n                advance('.');\n                if (!next_token.identifier) {\n                    warn('expected_class_a');\n                }\n                advance();\n                break;\n            case '[':\n                advance('[');\n                if (!next_token.identifier) {\n                    warn('expected_attribute_a');\n                }\n                advance();\n                if (next_token.id === '=' || next_token.value === '~=' ||\n                        next_token.value === '$=' ||\n                        next_token.value === '|=' ||\n                        next_token.id === '*=' ||\n                        next_token.id === '^=') {\n                    advance();\n                    if (next_token.arity !== 'string') {\n                        warn('expected_string_a');\n                    }\n                    advance();\n                }\n                advance(']');\n                break;\n            default:\n                fail('expected_selector_a');\n            }\n        }\n    }\n\n    function style_pattern() {\n        if (next_token.id === '{') {\n            warn('expected_style_pattern');\n        }\n        for (;;) {\n            style_selector();\n            if (next_token.id === '</' || next_token.id === '{' ||\n                    next_token.id === '(end)') {\n                return '';\n            }\n            if (next_token.id === ',') {\n                comma();\n            }\n        }\n    }\n\n    function style_list() {\n        while (next_token.id !== '</' && next_token.id !== '(end)') {\n            style_pattern();\n            xmode = 'styleproperty';\n            if (next_token.id === ';') {\n                semicolon();\n            } else {\n                advance('{');\n                substyle();\n                xmode = 'style';\n                advance('}');\n            }\n        }\n    }\n\n    function styles() {\n        var i;\n        while (next_token.id === '@') {\n            i = peek();\n            advance('@');\n            if (next_token.identifier) {\n                switch (next_token.value) {\n                case 'import':\n                    advance();\n                    if (!css_url()) {\n                        warn('expected_a_b',\n                            next_token, 'url', next_token.value);\n                        advance();\n                    }\n                    semicolon();\n                    break;\n                case 'media':\n                    advance();\n                    for (;;) {\n                        if (!next_token.identifier || css_media[next_token.value] === true) {\n                            fail('expected_media_a');\n                        }\n                        advance();\n                        if (next_token.id !== ',') {\n                            break;\n                        }\n                        comma();\n                    }\n                    advance('{');\n                    style_list();\n                    advance('}');\n                    break;\n                default:\n                    warn('expected_at_a');\n                }\n            } else {\n                warn('expected_at_a');\n            }\n        }\n        style_list();\n    }\n\n\n// Parse HTML\n\n    function do_begin(n) {\n        if (n !== 'html' && !option.fragment) {\n            if (n === 'div' && option.adsafe) {\n                fail('adsafe_fragment');\n            } else {\n                fail('expected_a_b', token, 'html', n);\n            }\n        }\n        if (option.adsafe) {\n            if (n === 'html') {\n                fail('adsafe_html', token);\n            }\n            if (option.fragment) {\n                if (n !== 'div') {\n                    fail('adsafe_div', token);\n                }\n            } else {\n                fail('adsafe_fragment', token);\n            }\n        }\n        option.browser = true;\n        assume();\n    }\n\n    function do_attribute(n, a, v) {\n        var u, x;\n        if (a === 'id') {\n            u = typeof v === 'string' ? v.toUpperCase() : '';\n            if (ids[u] === true) {\n                warn('duplicate_a', next_token, v);\n            }\n            if (!/^[A-Za-z][A-Za-z0-9._:\\-]*$/.test(v)) {\n                warn('bad_id_a', next_token, v);\n            } else if (option.adsafe) {\n                if (adsafe_id) {\n                    if (v.slice(0, adsafe_id.length) !== adsafe_id) {\n                        warn('adsafe_prefix_a', next_token, adsafe_id);\n                    } else if (!/^[A-Z]+_[A-Z]+$/.test(v)) {\n                        warn('adsafe_bad_id');\n                    }\n                } else {\n                    adsafe_id = v;\n                    if (!/^[A-Z]+_$/.test(v)) {\n                        warn('adsafe_bad_id');\n                    }\n                }\n            }\n            x = v.search(dx);\n            if (x >= 0) {\n                warn('unexpected_char_a_b', token, v.charAt(x), a);\n            }\n            ids[u] = true;\n        } else if (a === 'class' || a === 'type' || a === 'name') {\n            x = v.search(qx);\n            if (x >= 0) {\n                warn('unexpected_char_a_b', token, v.charAt(x), a);\n            }\n            ids[u] = true;\n        } else if (a === 'href' || a === 'background' ||\n                a === 'content' || a === 'data' ||\n                a.indexOf('src') >= 0 || a.indexOf('url') >= 0) {\n            if (option.safe && ux.test(v)) {\n                fail('bad_url', next_token, v);\n            }\n            urls.push(v);\n        } else if (a === 'for') {\n            if (option.adsafe) {\n                if (adsafe_id) {\n                    if (v.slice(0, adsafe_id.length) !== adsafe_id) {\n                        warn('adsafe_prefix_a', next_token, adsafe_id);\n                    } else if (!/^[A-Z]+_[A-Z]+$/.test(v)) {\n                        warn('adsafe_bad_id');\n                    }\n                } else {\n                    warn('adsafe_bad_id');\n                }\n            }\n        } else if (a === 'name') {\n            if (option.adsafe && v.indexOf('_') >= 0) {\n                warn('adsafe_name_a', next_token, v);\n            }\n        }\n    }\n\n    function do_tag(name, attribute) {\n        var i, tag = html_tag[name], script, x;\n        src = false;\n        if (!tag) {\n            fail(\n                bundle.unrecognized_tag_a,\n                next_token,\n                name === name.toLowerCase() ? name : name + ' (capitalization error)'\n            );\n        }\n        if (stack.length > 0) {\n            if (name === 'html') {\n                fail('unexpected_a', token, name);\n            }\n            x = tag.parent;\n            if (x) {\n                if (x.indexOf(' ' + stack[stack.length - 1].name + ' ') < 0) {\n                    fail('tag_a_in_b', token, name, x);\n                }\n            } else if (!option.adsafe && !option.fragment) {\n                i = stack.length;\n                do {\n                    if (i <= 0) {\n                        fail('tag_a_in_b', token, name, 'body');\n                    }\n                    i -= 1;\n                } while (stack[i].name !== 'body');\n            }\n        }\n        switch (name) {\n        case 'div':\n            if (option.adsafe && stack.length === 1 && !adsafe_id) {\n                warn('adsafe_missing_id');\n            }\n            break;\n        case 'script':\n            xmode = 'script';\n            advance('>');\n            if (attribute.lang) {\n                warn('lang', token);\n            }\n            if (option.adsafe && stack.length !== 1) {\n                warn('adsafe_placement', token);\n            }\n            if (attribute.src) {\n                if (option.adsafe && (!adsafe_may || !approved[attribute.src])) {\n                    warn('adsafe_source', token);\n                }\n                if (attribute.type) {\n                    warn('type', token);\n                }\n            } else {\n                step_in(next_token.from);\n                edge();\n                use_strict();\n                adsafe_top = true;\n                script = statements();\n\n// JSLint is also the static analyzer for ADsafe. See www.ADsafe.org.\n\n                if (option.adsafe) {\n                    if (adsafe_went) {\n                        fail('adsafe_script', token);\n                    }\n                    if (script.length !== 1 ||\n                            aint(script[0],             'id',    '(') ||\n                            aint(script[0].first,       'id',    '.') ||\n                            aint(script[0].first.first, 'value', 'ADSAFE') ||\n                            aint(script[0].second[0],   'value', adsafe_id)) {\n                        fail('adsafe_id_go');\n                    }\n                    switch (script[0].first.second.value) {\n                    case 'id':\n                        if (adsafe_may || script[0].second.length !== 1) {\n                            fail('adsafe_id', next_token);\n                        }\n                        adsafe_may = true;\n                        break;\n                    case 'go':\n                        if (!adsafe_may) {\n                            fail('adsafe_id');\n                        }\n                        if (script[0].second.length !== 2 ||\n                                aint(script[0].second[1], 'id', 'function') ||\n                                script[0].second[1].first.length !== 2 ||\n                                aint(script[0].second[1].first[0], 'value', 'dom') ||\n                                aint(script[0].second[1].first[1], 'value', 'lib')) {\n                            fail('adsafe_go', next_token);\n                        }\n                        adsafe_went = true;\n                        break;\n                    default:\n                        fail('adsafe_id_go');\n                    }\n                }\n                indent = null;\n            }\n            xmode = 'html';\n            advance('</');\n            if (!next_token.identifier && next_token.value !== 'script') {\n                warn('expected_a_b', next_token, 'script', next_token.value);\n            }\n            advance();\n            xmode = 'outer';\n            break;\n        case 'style':\n            xmode = 'style';\n            advance('>');\n            styles();\n            xmode = 'html';\n            advance('</');\n            if (!next_token.identifier && next_token.value !== 'style') {\n                warn('expected_a_b', next_token, 'style', next_token.value);\n            }\n            advance();\n            xmode = 'outer';\n            break;\n        case 'input':\n            switch (attribute.type) {\n            case 'radio':\n            case 'checkbox':\n            case 'button':\n            case 'reset':\n            case 'submit':\n                break;\n            case 'text':\n            case 'file':\n            case 'password':\n            case 'file':\n            case 'hidden':\n            case 'image':\n                if (option.adsafe && attribute.autocomplete !== 'off') {\n                    warn('adsafe_autocomplete');\n                }\n                break;\n            default:\n                warn('bad_type');\n            }\n            break;\n        case 'applet':\n        case 'body':\n        case 'embed':\n        case 'frame':\n        case 'frameset':\n        case 'head':\n        case 'iframe':\n        case 'noembed':\n        case 'noframes':\n        case 'object':\n        case 'param':\n            if (option.adsafe) {\n                warn('adsafe_tag', next_token, name);\n            }\n            break;\n        }\n    }\n\n\n    function closetag(name) {\n        return '</' + name + '>';\n    }\n\n    function html() {\n        var attribute, attributes, is_empty, name, old_white = option.white,\n            quote, tag_name, tag, wmode;\n        xmode = 'html';\n        xquote = '';\n        stack = null;\n        for (;;) {\n            switch (next_token.value) {\n            case '<':\n                xmode = 'html';\n                advance('<');\n                attributes = {};\n                tag_name = next_token;\n                if (!tag_name.identifier) {\n                    warn('bad_name_a', tag_name);\n                }\n                name = tag_name.value;\n                if (option.cap) {\n                    name = name.toLowerCase();\n                }\n                tag_name.name = name;\n                advance();\n                if (!stack) {\n                    stack = [];\n                    do_begin(name);\n                }\n                tag = html_tag[name];\n                if (typeof tag !== 'object') {\n                    fail('unrecognized_tag_a', tag_name, name);\n                }\n                is_empty = tag.empty;\n                tag_name.type = name;\n                for (;;) {\n                    if (next_token.id === '/') {\n                        advance('/');\n                        if (next_token.id !== '>') {\n                            warn('expected_a_b', next_token, '>', next_token.value);\n                        }\n                        break;\n                    }\n                    if (next_token.id && next_token.id.substr(0, 1) === '>') {\n                        break;\n                    }\n                    if (!next_token.identifier) {\n                        if (next_token.id === '(end)' || next_token.id === '(error)') {\n                            warn('expected_a_b', next_token, '>', next_token.value);\n                        }\n                        warn('bad_name_a');\n                    }\n                    option.white = true;\n                    spaces();\n                    attribute = next_token.value;\n                    option.white = old_white;\n                    advance();\n                    if (!option.cap && attribute !== attribute.toLowerCase()) {\n                        warn('attribute_case_a', token);\n                    }\n                    attribute = attribute.toLowerCase();\n                    xquote = '';\n                    if (Object.prototype.hasOwnProperty.call(attributes, attribute)) {\n                        warn('duplicate_a', token, attribute);\n                    }\n                    if (attribute.slice(0, 2) === 'on') {\n                        if (!option.on) {\n                            warn('html_handlers');\n                        }\n                        xmode = 'scriptstring';\n                        advance('=');\n                        quote = next_token.id;\n                        if (quote !== '\"' && quote !== '\\'') {\n                            fail('expected_a_b', next_token, '\"', next_token.value);\n                        }\n                        xquote = quote;\n                        wmode = option.white;\n                        option.white = false;\n                        advance(quote);\n                        use_strict();\n                        statements();\n                        option.white = wmode;\n                        if (next_token.id !== quote) {\n                            fail('expected_a_b', next_token, quote, next_token.value);\n                        }\n                        xmode = 'html';\n                        xquote = '';\n                        advance(quote);\n                        tag = false;\n                    } else if (attribute === 'style') {\n                        xmode = 'scriptstring';\n                        advance('=');\n                        quote = next_token.id;\n                        if (quote !== '\"' && quote !== '\\'') {\n                            fail('expected_a_b', next_token, '\"', next_token.value);\n                        }\n                        xmode = 'styleproperty';\n                        xquote = quote;\n                        advance(quote);\n                        substyle();\n                        xmode = 'html';\n                        xquote = '';\n                        advance(quote);\n                        tag = false;\n                    } else {\n                        if (next_token.id === '=') {\n                            advance('=');\n                            tag = next_token.value;\n                            if (!next_token.identifier &&\n                                    next_token.id !== '\"' &&\n                                    next_token.id !== '\\'' &&\n                                    next_token.arity !== 'string' &&\n                                    next_token.arity !== 'number' &&\n                                    next_token.id !== '(color)') {\n                                warn('expected_attribute_value_a', token, attribute);\n                            }\n                            advance();\n                        } else {\n                            tag = true;\n                        }\n                    }\n                    attributes[attribute] = tag;\n                    do_attribute(name, attribute, tag);\n                }\n                do_tag(name, attributes);\n                if (!is_empty) {\n                    stack.push(tag_name);\n                }\n                xmode = 'outer';\n                advance('>');\n                break;\n            case '</':\n                xmode = 'html';\n                advance('</');\n                if (!next_token.identifier) {\n                    warn('bad_name_a');\n                }\n                name = next_token.value;\n                if (option.cap) {\n                    name = name.toLowerCase();\n                }\n                advance();\n                if (!stack) {\n                    fail('unexpected_a', next_token, closetag(name));\n                }\n                tag_name = stack.pop();\n                if (!tag_name) {\n                    fail('unexpected_a', next_token, closetag(name));\n                }\n                if (tag_name.name !== name) {\n                    fail('expected_a_b',\n                        next_token, closetag(tag_name.name), closetag(name));\n                }\n                if (next_token.id !== '>') {\n                    fail('expected_a_b', next_token, '>', next_token.value);\n                }\n                xmode = 'outer';\n                advance('>');\n                break;\n            case '<!':\n                if (option.safe) {\n                    warn('adsafe_a');\n                }\n                xmode = 'html';\n                for (;;) {\n                    advance();\n                    if (next_token.id === '>' || next_token.id === '(end)') {\n                        break;\n                    }\n                    if (next_token.value.indexOf('--') >= 0) {\n                        fail('unexpected_a', next_token, '--');\n                    }\n                    if (next_token.value.indexOf('<') >= 0) {\n                        fail('unexpected_a', next_token, '<');\n                    }\n                    if (next_token.value.indexOf('>') >= 0) {\n                        fail('unexpected_a', next_token, '>');\n                    }\n                }\n                xmode = 'outer';\n                advance('>');\n                break;\n            case '(end)':\n                return;\n            default:\n                if (next_token.id === '(end)') {\n                    fail('missing_a', next_token,\n                        '</' + stack[stack.length - 1].value + '>');\n                } else {\n                    advance();\n                }\n            }\n            if (stack && stack.length === 0 && (option.adsafe ||\n                    !option.fragment || next_token.id === '(end)')) {\n                break;\n            }\n        }\n        if (next_token.id !== '(end)') {\n            fail('unexpected_a');\n        }\n    }\n\n\n// The actual JSLINT function itself.\n\n    var itself = function (the_source, the_option) {\n        var i, keys, predef;\n        JSLINT.comments = [];\n        JSLINT.errors = [];\n        JSLINT.tree = '';\n        begin = older_token = prev_token = token = next_token =\n            Object.create(syntax['(begin)']);\n        predefined = Object.create(standard);\n        if (the_option) {\n            option = Object.create(the_option);\n            predef = option.predef;\n            if (predef) {\n                if (Array.isArray(predef)) {\n                    for (i = 0; i < predef.length; i += 1) {\n                        predefined[predef[i]] = true;\n                    }\n                } else if (typeof predef === 'object') {\n                    keys = Object.keys(predef);\n                    for (i = 0; i < keys.length; i += 1) {\n                        predefined[keys[i]] = !!predef[keys];\n                    }\n                }\n            }\n            if (option.adsafe) {\n                option.safe = true;\n            }\n            if (option.safe) {\n                option.browser     =\n                    option['continue'] =\n                    option.css     =\n                    option.debug   =\n                    option.devel   =\n                    option.evil    =\n                    option.forin   =\n                    option.on      =\n                    option.rhino   =\n                    option.sub     =\n                    option.widget  =\n                    option.windows = false;\n\n                option.nomen       =\n                    option.strict  =\n                    option.undef   = true;\n\n                predefined.Date         =\n                    predefined['eval']  =\n                    predefined.Function =\n                    predefined.Object   = null;\n\n                predefined.ADSAFE  =\n                    predefined.lib = false;\n            }\n        } else {\n            option = {};\n        }\n        option.indent = +option.indent || 0;\n        option.maxerr = option.maxerr || 50;\n        adsafe_id = '';\n        adsafe_may = adsafe_top = adsafe_went = false;\n        approved = {};\n        if (option.approved) {\n            for (i = 0; i < option.approved.length; i += 1) {\n                approved[option.approved[i]] = option.approved[i];\n            }\n        } else {\n            approved.test = 'test';\n        }\n        tab = '';\n        for (i = 0; i < option.indent; i += 1) {\n            tab += ' ';\n        }\n        global = Object.create(predefined);\n        scope = global;\n        funct = {\n            '(global)': true,\n            '(name)': '(global)',\n            '(scope)': scope,\n            '(breakage)': 0,\n            '(loopage)': 0\n        };\n        functions = [funct];\n\n        comments_off = false;\n        ids = {};\n        implied = {};\n        in_block = false;\n        indent = false;\n        json_mode = false;\n        lookahead = [];\n        member = {};\n        properties = null;\n        prereg = true;\n        src = false;\n        stack = null;\n        strict_mode = false;\n        urls = [];\n        var_mode = false;\n        warnings = 0;\n        xmode = false;\n        lex.init(the_source);\n\n        assume();\n\n        try {\n            advance();\n            if (next_token.arity === 'number') {\n                fail('unexpected_a');\n            } else if (next_token.value.charAt(0) === '<') {\n                html();\n                if (option.adsafe && !adsafe_went) {\n                    warn('adsafe_go', this);\n                }\n            } else {\n                switch (next_token.id) {\n                case '{':\n                case '[':\n                    json_mode = true;\n                    json_value();\n                    break;\n                case '@':\n                case '*':\n                case '#':\n                case '.':\n                case ':':\n                    xmode = 'style';\n                    advance();\n                    if (token.id !== '@' || !next_token.identifier ||\n                            next_token.value !== 'charset' || token.line !== 1 ||\n                            token.from !== 1) {\n                        fail('css');\n                    }\n                    advance();\n                    if (next_token.arity !== 'string' &&\n                            next_token.value !== 'UTF-8') {\n                        fail('css');\n                    }\n                    advance();\n                    semicolon();\n                    styles();\n                    break;\n\n                default:\n                    if (option.adsafe && option.fragment) {\n                        fail('expected_a_b',\n                            next_token, '<div>', next_token.value);\n                    }\n\n// If the first token is predef semicolon, ignore it. This is sometimes used when\n// files are intended to be appended to files that may be sloppy. predef sloppy\n// file may be depending on semicolon insertion on its last line.\n\n                    step_in(1);\n                    if (next_token.id === ';') {\n                        semicolon();\n                    }\n                    if (next_token.value === 'use strict') {\n                        warn('function_strict');\n                        use_strict();\n                    }\n                    adsafe_top = true;\n                    begin.first = statements();\n                    JSLINT.tree = begin;\n                    if (option.adsafe && (JSLINT.tree.length !== 1 ||\n                            aint(JSLINT.tree[0], 'id', '(') ||\n                            aint(JSLINT.tree[0].first, 'id', '.') ||\n                            aint(JSLINT.tree[0].first.first, 'value', 'ADSAFE') ||\n                            aint(JSLINT.tree[0].first.second, 'value', 'lib') ||\n                            JSLINT.tree[0].second.length !== 2 ||\n                            JSLINT.tree[0].second[0].arity !== 'string' ||\n                            aint(JSLINT.tree[0].second[1], 'id', 'function'))) {\n                        fail('adsafe_lib');\n                    }\n                    if (JSLINT.tree.disrupt) {\n                        warn('weird_program', prev_token);\n                    }\n                }\n            }\n            indent = null;\n            advance('(end)');\n        } catch (e) {\n            if (e) {        // `~\n                JSLINT.errors.push({\n                    reason    : e.message,\n                    line      : e.line || next_token.line,\n                    character : e.character || next_token.from\n                }, null);\n            }\n        }\n        return JSLINT.errors.length === 0;\n    };\n\n\n// Data summary.\n\n    itself.data = function () {\n        var data = {functions: []},\n            function_data,\n            globals,\n            i,\n            implieds = [],\n            j,\n            kind,\n            members = [],\n            name,\n            the_function,\n            unused = [];\n        if (itself.errors.length) {\n            data.errors = itself.errors;\n        }\n\n        if (json_mode) {\n            data.json = true;\n        }\n\n        for (name in implied) {\n            if (Object.prototype.hasOwnProperty.call(implied, name)) {\n                implieds.push({\n                    name: name,\n                    line: implied[name]\n                });\n            }\n        }\n        if (implieds.length > 0) {\n            data.implieds = implieds;\n        }\n\n        if (urls.length > 0) {\n            data.urls = urls;\n        }\n\n        globals = Object.keys(functions[0]).filter(function (value) {\n            return value.charAt(0) !== '(' ? value : undefined;\n        });\n        if (globals.length > 0) {\n            data.globals = globals;\n        }\n\n        for (i = 1; i < functions.length; i += 1) {\n            the_function = functions[i];\n            function_data = {};\n            for (j = 0; j < functionicity.length; j += 1) {\n                function_data[functionicity[j]] = [];\n            }\n            for (name in the_function) {\n                if (Object.prototype.hasOwnProperty.call(the_function, name)) {\n                    if (name.charAt(0) !== '(') {\n                        kind = the_function[name];\n                        if (kind === 'unction') {\n                            kind = 'unused';\n                        } else if (typeof kind === 'boolean') {\n                            kind = 'global';\n                        }\n                        if (Array.isArray(function_data[kind])) {\n                            function_data[kind].push(name);\n                            if (kind === 'unused') {\n                                unused.push({\n                                    name: name,\n                                    line: the_function['(line)'],\n                                    'function': the_function['(name)']\n                                });\n                            }\n                        }\n                    }\n                }\n            }\n            for (j = 0; j < functionicity.length; j += 1) {\n                if (function_data[functionicity[j]].length === 0) {\n                    delete function_data[functionicity[j]];\n                }\n            }\n            function_data.name = the_function['(name)'];\n            function_data.param = the_function['(params)'];\n            function_data.line = the_function['(line)'];\n            data.functions.push(function_data);\n        }\n\n        if (unused.length > 0) {\n            data.unused = unused;\n        }\n\n        members = [];\n        for (name in member) {\n            if (typeof member[name] === 'number') {\n                data.member = member;\n                break;\n            }\n        }\n\n        return data;\n    };\n\n\n    itself.report = function (errors_only) {\n        var data = itself.data();\n\n        var err, evidence, i, j, key, keys, length, mem = '', name, names,\n            output = [], snippets, the_function, warning;\n\n        function detail(h, array) {\n            var comma_needed, i, singularity;\n            if (array) {\n                output.push('<div><i>' + h + '</i> ');\n                array = array.sort();\n                for (i = 0; i < array.length; i += 1) {\n                    if (array[i] !== singularity) {\n                        singularity = array[i];\n                        output.push((comma_needed ? ', ' : '') + singularity);\n                        comma_needed = true;\n                    }\n                }\n                output.push('</div>');\n            }\n        }\n\n        if (data.errors || data.implieds || data.unused) {\n            err = true;\n            output.push('<div id=errors><i>Error:</i>');\n            if (data.errors) {\n                for (i = 0; i < data.errors.length; i += 1) {\n                    warning = data.errors[i];\n                    if (warning) {\n                        evidence = warning.evidence || '';\n                        output.push('<p>Problem' + (isFinite(warning.line) ? ' at line ' +\n                            warning.line + ' character ' + warning.character : '') +\n                            ': ' + warning.reason.entityify() +\n                            '</p><p class=evidence>' +\n                            (evidence && (evidence.length > 80 ? evidence.slice(0, 77) + '...' :\n                            evidence).entityify()) + '</p>');\n                    }\n                }\n            }\n\n            if (data.implieds) {\n                snippets = [];\n                for (i = 0; i < data.implieds.length; i += 1) {\n                    snippets[i] = '<code>' + data.implieds[i].name + '</code>&nbsp;<i>' +\n                        data.implieds[i].line + '</i>';\n                }\n                output.push('<p><i>Implied global:</i> ' + snippets.join(', ') + '</p>');\n            }\n\n            if (data.unused) {\n                snippets = [];\n                for (i = 0; i < data.unused.length; i += 1) {\n                    snippets[i] = '<code><u>' + data.unused[i].name + '</u></code>&nbsp;<i>' +\n                        data.unused[i].line + ' </i> <small>' +\n                        data.unused[i]['function'] + '</small>';\n                }\n                output.push('<p><i>Unused variable:</i> ' + snippets.join(', ') + '</p>');\n            }\n            if (data.json) {\n                output.push('<p>JSON: bad.</p>');\n            }\n            output.push('</div>');\n        }\n\n        if (!errors_only) {\n\n            output.push('<br><div id=functions>');\n\n            if (data.urls) {\n                detail(\"URLs<br>\", data.urls, '<br>');\n            }\n\n            if (xmode === 'style') {\n                output.push('<p>CSS.</p>');\n            } else if (data.json && !err) {\n                output.push('<p>JSON: good.</p>');\n            } else if (data.globals) {\n                output.push('<div><i>Global</i> ' +\n                    data.globals.sort().join(', ') + '</div>');\n            } else {\n                output.push('<div><i>No new global variables introduced.</i></div>');\n            }\n\n            for (i = 0; i < data.functions.length; i += 1) {\n                the_function = data.functions[i];\n                names = [];\n                if (the_function.param) {\n                    for (j = 0; j < the_function.param.length; j += 1) {\n                        names[j] = the_function.param[j].value;\n                    }\n                }\n                output.push('<br><div class=function><i>' + the_function.line + '</i> ' +\n                    (the_function.name || '') + '(' + names.join(', ') + ')</div>');\n                detail('<big><b>Unused</b></big>', the_function.unused);\n                detail('Closure', the_function.closure);\n                detail('Variable', the_function['var']);\n                detail('Exception', the_function.exception);\n                detail('Outer', the_function.outer);\n                detail('Global', the_function.global);\n                detail('Label', the_function.label);\n            }\n\n            if (data.member) {\n                keys = Object.keys(data.member);\n                if (keys.length) {\n                    keys = keys.sort();\n                    mem = '<br><pre id=properties>/*properties ';\n                    length = 13;\n                    for (i = 0; i < keys.length; i += 1) {\n                        key = keys[i];\n                        name = key.name();\n                        if (length + name.length > 72) {\n                            output.push(mem + '<br>');\n                            mem = '    ';\n                            length = 1;\n                        }\n                        length += name.length + 2;\n                        if (data.member[key] === 1) {\n                            name = '<i>' + name + '</i>';\n                        }\n                        if (i < keys.length - 1) {\n                            name += ', ';\n                        }\n                        mem += name;\n                    }\n                    output.push(mem + '<br>*/</pre>');\n                }\n                output.push('</div>');\n            }\n        }\n        return output.join('');\n    };\n    itself.jslint = itself;\n\n    itself.edition = '2011-03-29';\n\n    return itself;\n\n}());\n// END JSLint (Replace all above code when changing JSLint versions)\n\n\n\n// Command line integration via Rhino\n(function (args) {\n    var name = args[0],\n        optstr = args[1], // arg1=val1,arg2=val2,...\n        opts = { rhino: true },\n        input;\n\n    if (!name) {\n        print('No files present in the fileset; Check your pattern match in build.xml');\n        quit(1);\n    }\n\n    if (optstr) {\n        optstr.split(',').forEach(function (arg) {\n            var o = arg.split('=');\n            opts[o[0]] = (function (ov) {\n                switch (ov) {\n                case 'true':\n                    return true;\n                case 'false':\n                    return false;\n                default:\n                    return ov;\n                }\n            })(o[1]);\n        });\n    }\n\n    input = readFile(name);\n\n    if (!input) {\n        print('JSLint: Couldn\\'t open file ' + name);\n        quit(1);\n    }\n    if (!JSLINT(input, opts)) {\n        for (var i = 0, err; err = JSLINT.errors[i]; i++) {\n            print(err.reason + ' (line: ' + err.line + ', character: ' + err.character + ')');\n            print('> ' + (err.evidence || '').replace(/^\\s*(\\S*(\\s+\\S+)*)\\s*$/, \"$1\"));\n            print('');\n        }\n        quit(1);\n    }\n\n    quit(0);\n}(arguments));\n"
  },
  {
    "path": "build/tools/optipng-0.6.4-exe/LICENSE.txt",
    "content": "\nCopyright (C) 2001-2010 Cosmin Truta.\n\nThis software is provided 'as-is', without any express or implied\nwarranty.  In no event will the author(s) be held liable for any damages\narising from the use of this software.\n\nPermission is granted to anyone to use this software for any purpose,\nincluding commercial applications, and to alter it and redistribute it\nfreely, subject to the following restrictions:\n\n1. The origin of this software must not be misrepresented; you must not\n   claim that you wrote the original software.  If you use this software\n   in a product, an acknowledgment in the product documentation would be\n   appreciated but is not required.\n\n2. Altered source versions must be plainly marked as such, and must not\n   be misrepresented as being the original software.\n\n3. This notice may not be removed or altered from any source distribution.\n\n"
  },
  {
    "path": "cn/index.html",
    "content": "<!DOCTYPE html public \"i ♥ the web\">\n<!--[if lt IE 9]>      <html class=\"no-js oldie no-fontface\" lang=\"zh-cn\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html class=\"no-js no-fontface\" lang=\"zh-cn\">   <!--<![endif]-->\n<head>\n    <meta charset=\"utf-8\">\n    <title>推动Web向前发展 | 如何参与网页标准和浏览器的演化</title>\n    <meta name=\"description\" content=\"前端开发人员能做的事情\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, minimum-scale=1\">\n\n    <!-- For iPhone 4 with high-resolution Retina display: -->\n    <link rel=\"apple-touch-icon-precomposed\" sizes=\"114x114\" href=\"apple-touch-icon-114x114-precomposed.png\">\n    <!-- For first-generation iPad: -->\n    <link rel=\"apple-touch-icon-precomposed\" sizes=\"72x72\" href=\"apple-touch-icon-72x72-precomposed.png\">\n    <!-- For non-Retina iPhone, iPod Touch, and Android 2.1+ devices: -->\n    <link rel=\"apple-touch-icon-precomposed\" href=\"apple-touch-icon-precomposed.png\">\n\n    <link rel=\"stylesheet\" href=\"../css/style.css\">\n\n    <!-- Should be combined: -->\n    <script src=\"../js/libs/modernizr.min.js\"></script>\n    <script src=\"../js/controller.js\"></script>\n</head>\n\n<body>\n  <b class=\"gimmick\"><i></i><i></i><i></i></b>\n    <header class=\"col-ab\">\n        <div class=\"lead\">\n            <h1 class=\"hed-lead\">推动Web向前发展<span></span></h1>\n            <h2 class=\"subhed-lead\">你可以让web变成你期望的那样。</h2>\n            <p class=\"subhed\">喜欢web标准，也想要回馈社区，却不知道从哪儿下手？ <b>让我们从这里开始吧。</b></p>\n        </div>\n        <div class=\"col-split\">\n            <p>不管你是一个天才web开发者、从table和<code>font</code>时代走过来的web老枪、还是一个骨灰级的电脑技术爱好者，都可以通过很多途径来回馈web平台，以下列出来的这些，任何人都可以去做。</p>\n            <p>我们的目标是让任何人都可以很容易的上手，开始为web这个平台做贡献，不管是去深入学习背后的工作原理、把经验分享给更多的人、还是编写具体的规范。web的成长源于你这样的贡献者，因此我们想让你们这些贡献者回馈的时候变得更加方便。</p>\n\t\t\t<p>其他版本：<a href=\"../\">English</a>、<a href=\"../ar\">عربى</a>。</p>\n        </div>\n    </header>\n\n    <div id=\"nav_container\">\n      <nav id=\"toc\">\n        <ul>\n          <li><a href=#levelup>炼级</a></li>\n          <li><a href=#digdeep>入戏</a></li>\n          <li><a href=#virtuoso>大家</a></li>\n        </ul>\n      </nav>\n    </div>\n\n    <article class=\"section\">\n        <div class=\"standout\" id=levelup>\n            <h1 class=\"hed\">炼级</h1>\n            <h2 class=\"subhed\">在处理工作相关的技术问题上你已经十分厉害了，接下来让我们投入到社区中去吧！</h2>\n        </div>\n\n        <section id=\"learn\" class=\"col-ab\">\n            <div class=\"col-a\">\n              <h1 class=\"hed\">学习</h1>\n              <p>不断变化是web的一个重要特点，当这些变化发生的时候，我们需要迎头赶上。以下是一些非常有用的资源，可以让你了解浏览器工作原理，掌握他们的最新动态和特性更新。</p>\n\n              <h2 id=\"how_do_i_keep_up_with_what8217s_landing_in_browsers\" class=\"subhed\">紧跟浏览器们的步伐</h2>\n              <ul>\n                <li><a href=\"http://updates.html5rocks.com/2011/10/Keeping-up-with-HTML5-and-browser-support\">HTML5新特性和浏览器兼容性</a> - HTML5和浏览器资讯相关资源列表\n                <li><a href=\"http://peter.sh/\">Peter Beverloo&#8217;s Blog</a> - WebKit和Chrome相关，每周更新\n                <li><a href=\"http://blog.whatwg.org/\">The WHATWG Blog</a> - web标准相关议案的每周摘要\n                <li><a href=\"http://www.w3.org/QA/archive/open_web/\">W3C&#8217;s open web</a> - html、css、SVG、Web APIs、EcmaScript/JavaScript、HTTP等相关，每周更新\n                <li><a href=\"http://my.opera.com/ODIN/blog/\">Opera Developer News</a> - Opera平台的相关资讯\n                <li><a href=\"http://updates.html5rocks.com\">HTML5 Rocks updates</a> - HTML5和Chrome相关资讯\n                <li><a href=\"http://hacks.mozilla.org/\">Mozilla Hacks</a> - 炫酷的apps和各种HTML5特性\n                <li><a href=\"http://blogs.msdn.com/b/ie/\">IE Blog</a> - IE最新消息\n              </ul>\n\n              <h3 id=\"follow_them_on_twitter\" class=\"subhed\">在Twitter上Follow这些帐号</h3>\n                <p>\n                  <a href=\"http://twitter.com/oDevRel\">@oDevRel</a> (Opera developer relations)， <a href=\"http://twitter.com/ChromiumDev\">@ChromiumDev</a> (Chrome developer relations)， <a href=\"http://twitter.com/mozhacks\">@mozhacks</a> (Mozilla's web developer outpost) & <a href=\"http://twitter.com/ie\">@IE</a> (Internet Explorer Team)。\n                </p>\n\n              <h2 id=\"how_do_i_understand_how_browsers_work\" class=\"subhed\">了解浏览器的工作原理？</h2>\n\n              <ul>\n                <li><a href=\"http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/\">How Browsers Work: Behind the Scenes of Modern Web Browsers</a> - 深度剖析浏览器是怎么工作的</li>\n                <li><a href=\"http://ontwik.com/javascript/txjs-2011-a9-alex-russell-life-of-a-button-element/?utm_source=feedburner&utm_medium=twitter&utm_campaign=Feed%3A+Ontwik+%28Ontwik%29\">Life of a &lt;button> element (by Alex Russell)</a> - 关于布局渲染和CSS(vimeo视频-GFW)</li>\n              </ul>\n\n              <h2 id=\"other_learning_resources\" class=\"subhed\">其他学习资源</h2>\n\n              <ul>\n                <li><a href=\"http://www.qianduan.net/\">前端观察</a> - 为前端技术人员提供所需的资讯及资源。</li>\n                <li><a href=\"http://css-tricks.com\">CSS-tricks</a> - 提供大量的文章、教程、下载资源。</li>\n                <li><a href=\"http://html5doctor.com\">HTML5doctor</a> - 关于HTML5、她的语义化、以及如何在项目中马上应用。</li>\n                <li><a href=\"http://diveintohtml5.info/\">Dive into HTML5</a> - 深度解析部分HTML5特性。</li>\n                <li><a href=\"http://addyosmani.com/blog/\">Addy Osmani&#8217;s blog</a> - jQuery、JavaScript、HTML5、CSS3相关的大量干货，作者已被google Chrome team 收编。</li>\n                <li><a href=\"http://paulirish.com\">Paul Irish&#8217;s blog</a> - Paul Irish大牛，不局限于某项具体的技术，各种最新最酷。</li>\n                <li><a href=\"http://dev.opera.com\">Dev.Opera</a> - HTML5特性相关的各种文章。</li>\n                <li><a href=\"http://paulirish.com/2011/web-browser-frontend-and-standards-feeds-to-follow/\">浏览器、前端、标准相关的feeds集合。</a> </li>\n                <li><a href=\"http://yuilibrary.com/theater/\">YUI Theater</a> - 前端开发web技术的视频。</li>\n                <li><a href=\"http://www.adobe.com/devnet/html5.html\">Adobe Developer Connection</a> - HTML5、CSS3、手机开发相关的文章和视频。</li>\n              </ul>\n\n              <h2 id=\"reference_docs_wikis\" class=\"subhed\">参考文档/wikis</h2>\n\n              <ul>\n                <li><a href=\"https://developer.mozilla.org/en-US/\">Mozilla&#8217;s MDN</a> - HTML、CSS、JavaScript、DOM...等相关的许多NB文档， 同时也可以贡献你自己的知识，请参考<a href=\"https://developer.mozilla.org/Project:en/How_to_Help\">怎么帮忙？</a> 如何<a href=\"https://developer.mozilla.org/Project:en/Getting_started\">上手</a>。</li>\n\t\t\t\t<li><a href=\"https://developer.mozilla.org/Writing_Forward_Compatible_Websites\">向前兼容的网站</a> - 让你的网站在最新版的浏览器中正常工作的一系列最佳实践</li>\n                <li><a href=\"http://html5please.com/\">HTML5 Please - Use new and shiny responsibly</a> - HTML5特性的浏览器兼容大全，方便查找、筛选各种特性。</li>\n              </ul>\n          </div>\n          <div class=\"col-b\">\n            <section class=\"getinvolved\">\n              <h2 class=\"subhed\">心痒了？</h2>\n              <div class=\"task\" data-hashtag=\"#learn\">\n                  <p>快速过一遍这些文章和tweets，你会发现有些东西和你理解的不一样！万事开头难，相信我们，只要你迈出了第一步，一切都会变得很容易。</p>\n                  <a href=\"#\" class=\"pledge\">我要参与！</a>\n                  <div class=\"pledges\"><p>下面是一些和你志同道合的开发者:</p></div>\n              </div>\n            </section>\n          </div>\n          </section>\n\n        <section id=\"meetups\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">多接触志趣相同者</h1>\n            <p>出席一些本地的专业会议是个不错的选择，可以与其他开发者的相互学习、共享资源、思想碰撞、建立合作关系。<a href=\"http://meetup.com\">Meetup</a> 和 <a href=\"http://lanyrd.com\">Lanyrd</a> 这些网站可以帮你找到你所在区域的会议。国内比较不错的有<a href=\"http://www.w3ctech.com/\">w3ctech</a>、<a href=\"http://www.webrebuild.org/\">webrebuild</a>、<a href=\"http://www.d2forum.org/\">d2论坛</a>等。</p>\n          </div>\n        </section>\n        <section id=\"askhelp\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">寻求帮助</h1>\n            <h2 id=\"answer_questions_and_participate_in_conversations_on_irc\" class=\"subhed\">在IRC上问问题、参加讨论</h2>\n            <p><a href=\"http://richard.esplins.org/siwi/2011/07/08/getting-started-freenode-irc/\">如何使用freenode和irc</a></p>\n            <ul>\n              <li><b>Freenode IRC 频道：</b> #html5 / #css / #javascript / #whatwg / #jquery / #yui / #dojo / #web / <span title=\"browser based game development\">#bbg</span> (on <a href=\"http://webchat.freenode.net\">irc.freenode.net</a>) </li>\n              <li id=\"mozilla_irc\"><b>Mozilla IRC 频道：</b> #js (on <a href=\"http://irc.mozilla.org\">irc.mozilla.org</a>)</li>\n            </ul>\n\n            <h2 id=\"how_to_ask_for_help\" class=\"subhed\">怎样寻求帮助</h2>\n            <ol class=\"tasks\">\n              <li>你需要先<a href=\"https://css-tricks.com/seriously-just-make-a-jsfiddle/\">在jsfiddle上做一个可以共享的demo</a>。</li>\n              <li><a href=\"https://css-tricks.com/reduced-test-cases/\">做一个精简的测试用例</a>。</li>\n              <li>记住：问题一定要具体、详细！</li>\n              <li>在IRC上、<a href=\"http://stackoverflow.com\">StackOverflow</a>(以及<a href=\"http://chat.stackoverflow.com/rooms/17/javascript\">javascript的聊天室</a>)上、朋友群(QQ群)上提问。\n            </ol>\n          </div>\n\n          <div class=\"col-b\">\n\t        <section class=\"getinvolved\">\n              <h2 class=\"subhed\">伸出援手</h2>\n              <div class=\"task\" data-hashtag=\"#ask4help\">\n                <p>我们都是依靠他人的帮助成长起来的。不要害羞，只管提问就是！但是要先在jsfiddle上做好你的Demo。 =D</p>\n                <a href=\"#\" class=\"pledge\">我要参与！</a>\n                <div class=\"pledges\"><p>下面是一些和你志同道合的开发者:</p></div>\n              </div>\n             </section>\n          </div>\n        </section>\n    </article>\n\n    <article class=\"section\">\n        <div class=\"standout\" id=digdeep>\n            <h1 class=\"hed\">入戏</h1>\n            <h2 class=\"subhed\">熟悉了舞台之后，就轮到你上场了。</h2>\n        </div>\n        <section id=\"helpothers\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">帮助他人</h1>\n            <p>我们都是过来人，帮助他人可以巩固你的知识，扩散你所领悟的一些想法、观点。以下是一些很好的开源项目，他们一致在寻求帮助。每一个补丁都是不容忽视的，不积跬步，无以至千里；不积小流，无以成江海。</p>\n\n            <h2 id=\"open_source_projects_worth_your_time\" class=\"subhed\">这些开源项目值得你为之付出。</h2>\n\n            <ul>\n              <li><a href=\"http://github.com/h5bp/html5-boilerplate\">HTML5 Boilerplate</a> <span>- 前端开发最佳实践交流</span>\n              <li><a href=\"https://github.com/jquery/learn.jquery.com\">jQuery Learning Site</a> <span>- 学习jQuery的网站</span>\n              <li><a href=\"https://github.com/jquery/jquery-mobile\">jQuery Mobile</a> <span>- 手机端渐进增强最佳实践</span>\n              <li><a href=\"https://github.com/Modernizr/Modernizr\">Modernizr</a> <span>- 最好的特性检测库，可以用作各种HTML5和CSS3的渐进增强和低版本浏览器兼容</span>\n              <li><a href=\"https://github.com/twbs/bootstrap\">Bootstrap</a> <span>- 一个快速启动webapp开发的工具包，包括css和js</span>\n              <li><a href=\"http://necolas.github.com/normalize.css/\">Normalize.css</a> <span>- 让标签在所有浏览器上表现一致</span>\n              <li><a href=\"http://dojotoolkit.org/get-involved\">Dojo</a> <span>- 综合性的前端工具包，可用于网站、终端、桌面应用开发</span>\n              <li><a href=\"https://github.com/h5bp/lazyweb-requests/issues?state=open\">Lazyweb requests</a> <span>- 为web开发者服务的，有创意、实用的工具和解决方案收集</span>\n            </ul>\n            <p>和上面所说的 <a href=\"#how_to_ask_for_help\">&#8216;如何寻求帮助&#8217;</a> 一样做， 同时去了解一下 <a href=\"http://addyosmani.com/blog/getting-involved-with-open-source/\">Addy Osmani关于如何参与的podcast</a>！</p>\n\n          </div>\n\n          <div class=\"col-b\">\n            <section class=\"getinvolved\">\n              <h2 class=\"subhed\">分享、传播</h2>\n              <div class=\"task\" data-hashtag=\"#helpothers\">\n                <p>多看好代码才能写出更NB的代码。深入研究下面这些项目，同时帮助她们不断成长，变得更好。</p>\n                <a href=\"#\" class=\"pledge\">我要参与！</a>\n                <div class=\"pledges\"><p>下面是一些和你志同道合的开发者:</p></div>\n              </div>\n            </section>\n          </div>\n        </section>\n\n        <section id=\"specs\" class=\"col-ab\">\n            <div class=\"col-a\">\n                <h1 class=\"hed\">为规范提供反馈</h1>\n\n                <p>规范描绘出我们想要的特性。她们是工作组在邮件列表中，通过热烈的讨论发展而来。我们不能保证所有的浏览器都会遵循规范中阐述的规则，各个浏览器会给我们这些开发者提供一些和标准冲突的东西。</p>\n\n                <ul>\n                    <li>学习 <a href=\"http://diveintohtml5.info/past.html\">HTML的历史</a>。</li>\n                    <li>去了解一下 <a href=\"http://fantasai.inkedblade.net/weblog/2011/inside-csswg/\">CSS工作组是如何运作的</a>。</li>\n                    <li>订阅这些邮件列表，跟进并参与那些推动web发展的讨论。\n                        <ul class=\"resources\">\n                            <li><a href=\"http://lists.w3.org/Archives/Public/public-webapps/\">public-webapps</a> -  Web Applications工作组的技术讨论</li>\n                            <li><a href=\"http://lists.w3.org/Archives/Public/www-style/\">www-style</a> - CSS和相关规范的讨论</li>\n                            <li><a href=\"http://lists.whatwg.org/pipermail/whatwg-whatwg.org/\">whatwg</a> - WHATWG的邮件列表</li>\n                            <li><a href=\"http://lists.w3.org/Archives/Public/public-html/\">public-html</a> - W3C HTML工作组</li>\n                            <li><a href=\"http://lists.w3.org/Archives/Public/www-dom/\">www-dom</a> - DOM相关</li>\n                            <li><a href=\"http://lists.w3.org/Archives/Public/public-fx/\">public-fx</a> - CSS和SVG工作组相关的问题讨论</li>\n                        </ul>\n                    </li>\n                    <li>仔细阅读 <a href=\"http://developers.whatwg.org/\">HTML5开发者规范</a> (去掉了实现机制部分，格式更美观)。</li>\n                    <li>对<a href=\"http://www.whatwg.org/specs/web-apps/current-work/multipage/\">HTML规范</a>进行注解和反馈最容易的方法：点击页面相关的部分，在页面下方的输入框输入你的想法，然后提交。</li>\n\t\t\t\t\t<li>\n                        在Twitter上关注HTML和CSS工作组的帐号，查看HTML和CSS规范的最新的注解：\n                        <ul class=\"resources\">\n                            <li><a href=\"http://twitter.com/whatwg\">@whatwg</a></li>\n                            <li><a href=\"http://twitter.com/csscommits\">@csscommits</a></li>\n                        </ul>\n                    </li>\n                </ul>\n            </div>\n            <div class=\"col-b\">\n              <section class=\"getinvolved\">\n                <h2 class=\"subhed\">你为规范出力了吗?</h2>\n                <div class=\"task\" data-hashtag=\"#feedback\">\n                  <p>我们是规范的使用者，为什么我们不帮助改善规范，让规范更合自己的胃口？支持标准，让规范越来越好！</p>\n                  <a href=\"#\" class=\"pledge\">我要参与！</a>\n                  <div class=\"pledges\"><p>下面是一些和你志同道合的开发者:</p></div>\n                </div>\n              </section>\n            </div>\n        </section>\n\n        <section id=\"explore\" class=\"col-ab\">\n            <div class=\"col-a\">\n              <h1 class=\"hed\">发掘前端特性</h1>\n              <p>当你掌握了最基本的东西，就可以开始深入研究当前(和未来)的web标准了！好激动啊，因为我们这里有高级CSS、新的HTML特性/API、以及这些语言被期望的美好憧憬。有些新特性已经被一些浏览器支持，发掘这些新特性，会帮助我们推动web不断前行。</p>\n\n            <h2 id=\"examples_of_how_to_explore_features_well\" class=\"subhed\">如何更好地发掘特性的例子</h2>\n            <ul>\n              <li><a href=\"http://perfectionkills.com/global-eval-what-are-the-options/\">全局 <code>eval</code>: 如何选择？</a> <span> - kangax</span>\n              <li><a href=\"http://nicolasgallagher.com/multiple-backgrounds-and-borders-with-css2/\">CSS2.1中的多背景、多边框</a>(:before/:after) <span> - Nicolas Gallagher</span>\n              <li><a href=\"http://nicolasgallagher.com/css-background-image-hacks/\">CSS background-image hacks</a>(:before/:after) <span> - Nicolas Gallagher</span>\n              <li><a href=\"http://www.webdirections.org/blog/let-the-web-move-you-css3-animations-and-transitions/\">让Web动起来 — CSS3 Animations和Transitions</a> <span> - John Allsopp</span>\n              <li><a href=\"http://addyosmani.com/largescalejavascript/\">大型可扩展JavaScript应用程序架构的模块</a> <span> - Addy Osmani</span>\n              <li><a href=\"http://designfestival.com/the-cicada-principle-and-why-it-matters-to-web-designers/\">什么是蝉原则，她为什么对web设计人员很重要(图片组合的多种可能性)</a> <span> - Alex Walker</span>\n              <li><a href=\"http://css-tricks.com/snippets/css/webkit-keyframe-animation-syntax/\">CSS关键帧动画的语法</a> <span> - Chris Coyier</span>\n              <li><a href=\"http://www.blog.highub.com/css/whats-new-in-css-selectors-level-4/\">CSS选择器新特性(CSS4)</a> <span> - Shi Chuan</span>\n              <li><a href=\"http://mathiasbynens.be/notes/touch-icons\">touch icons给移动设备的favicon</a> <span> - Mathias Bynens</span>\n              <li><a href=\"http://coding.smashingmagazine.com/2009/09/15/the-z-index-css-property-a-comprehensive-look/\">CSS中的z-index综述</a> <span> - Louis Lazaris</span>\n            </ul>\n\n            <h2 id=\"cool_ideas_to_explore_more\" class=\"subhed\">发掘更多的好特性(并写下来分享之)</h2>\n\n            <p>浏览器总是在不断发布新的CSS特性。我们总是厌恶的浏览器的这些私有属性，但是这些私有属性已经存在，我们这些开发者能做的，是反馈给浏览器厂商，这些私有属性是否能满足我们的需求。如果这个属性是你需要的，主动去研究、应用！ 这个 <a href=\"http://peter.sh/experiments/vendor-prefixed-css-property-overview/\">浏览器私有CSS属性纵览</a>，是Peter Beverloo整理的，有许多实验性的东西；许多还没有被完全理解。可以写一写文中提到的属性还有下面这些：\n\n\t\t\t  <ul>\n                <li><a href=\"https://developer.mozilla.org/En/CSS/%3Achecked\">:checked 伪类选择器</a> / <a href=\"http://dev.w3.org/csswg/css3-images/#object-fit\">object-fit</a>  / <a href=\"https://developer.mozilla.org/en/CSS/background-clip\">background-clip</a> / <a href=\"https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html\">fx blur css filter</a> / <a href=\"http://dropshado.ws/post/1015351370/webkit-line-clamp\">-webkit-line-clamp</a> / <a href=\"https://developer.mozilla.org/en/CSS/text-overflow\">text-overflow</a> / <a href=\"https://developer.mozilla.org/En/CSS/Box-sizing\">box-sizing</a> / <a href=\"https://developer.mozilla.org/en/CSS3_Columns\">CSS columns</a></li>\n                <li><code>history.pushState()</code>, HTML5 input <code>checkValidity()</code>, <code>getClientRects</code> / <code>getBoundingClientRect</code>, WebKit's <a href=\"http://developer.apple.com/library/safari/#documentation/DataManagement/Reference/DOMWindowAdditionsReference/DOMWindowAdditions/DOMWindowAdditions.html\">ConvertPointFromPageToNode</a>\n                <li><a href=\"http://www.w3.org/TR/css3-gcpm/\">CSS Generated Content for Paged Media Module (GCPM) 印刷出版物相关</a>\n                <li><code>word-wrap</code>、<code>word-break</code>和<code>white-space</code>之间的差异\n                <li>Harmony 的一些特性，比如 <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:let\">let</a> / <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:block_scoped_bindings\">block-scoped bindings</a> / block functions /  <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:destructuring\">destructuring</a> / <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:rest_parameters\">rest parameters</a> / <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:parameter_default_values\">default param values</a>.\n                <li><a href=\"http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html\">Web Components 释义</a>\n                <li><strong>以下这些分享中的任何特性：</strong>\n                  <ul>\n                    <li><a href=\"http://vimeo.com/32135328\">CSS的未来</a> <span>- 未来的CSS值得期待的东西 - Tab Atkins</span>\n                    <li><a href=\"http://infrequently.org/11/fronteers/fronteers.html\">数据、语义、进化过程 </a> <span>- 浏览器进化，Component模型，MDV(Model-Driven View)</span>\n                    <li><a href=\"http://infrequently.org/11/ldnjs/ldnjs.html\">[JS|DOM].next()</a> <span>- 下一代的ECMAScript - Alex Russell</span>\n                    <li><a href=\"http://lea.verou.me/css3-secrets/\">CSS3的10个秘密</a> <span>- 一个关于高级CSS3功能的互动展示</span>\n                    <li><a href=\"http://nimbu.in/w3conf/\">CSS布局的未来</a> <span>- and how emerging specs will add 合适的布局控制</span>\n                    <li><a href=\"http://mezzoblue.com/presentations/2011/fowd/FOWD.pdf\">CSS的未来</a> <span>- 一系列CSS新特性概览</span>\n                </ul>\n              </ul>\n\n            </div>\n            <div class=\"col-b\">\n\t          <section class=\"getinvolved\">\n                <h2 class=\"subhed\">探索未知的！</h2>\n                <div class=\"task\" data-hashtag=\"#explore\">\n                  <p>行动起来！推动web前行的唯一途径是发掘和使用各种高级特性和API。</p>\n                  <a href=\"#\" class=\"pledge\">我要参与！</a>\n                  <div class=\"pledges\"><p>下面是一些和你志同道合的开发者:</p></div>\n                </div>\n             </section>\n          </div>\n        </section>\n\n\n        <section id=\"write\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">写文章</h1>\n            <p>把你学到的东西写出来并发布在网上，不要害怕犯错。做一个你自己的博客，把你写的东西放上去，持续更新其内容。说出你自己的真实想法，不要人云亦云，这一点很重要。你的文章内容是不是绝对的正确、权威并不重要。保持提问、及时对话，世上没有错误的问题或者错误的答案。</p>\n\n            <p>教学相长，教是更有效的学习方法。即使只是初涉某个领域，写一些相关的文字也会对你自己有帮助。你可以请这方面的牛人或者朋友进行相关的技术评审。</p>\n\n            <h2 id=\"what_should_you_start_to_learn_about\" class=\"subhed\">你想写哪些方面的东西？</h2>\n\n            <p>你可以分享一些东西给他人！下面是一些不错的主意：</p>\n            <ul>\n                <li><code>&lt;br&gt;</code> 和 <code>&lt;hr&gt;</code> （或其他任何元素）存在的原因？</li>\n                <li>如何用最少的代码实现一个轮播？</li>\n                <li>DOM是什么？她为什么会存在？</li>\n                <li>看看浏览器是是如何实现规范中的某个条款的，并与规范进行比较。</li>\n                <li>分析某个流行的网站的首页（附上改进的建议）。</li>\n                <li>你会如何去弥补某个流行网站的短板（加载时间过长、无效的js脚本等）</li>\n                <li>分析一个流行的demo，用她做出另外的不一样的东西（或者在实际工作中应用她）。</li>\n                <li>总结最近流行某个概念或理念。</li>\n                <li>把你的经验贡献给某个开源项目。</li>\n                <li>CSS预处理（less、sass等）在管理不当的情况下是怎么造成不良后果的。</li>\n                <li>如果英语不是你的母语：\n                <ul class=\"resources\">\n                  <li>翻译时下流行的一些web开发相关的文章。</li>\n                  <li>详细说明规范中的某些特性。</li>\n                </ul>\n              </li>\n            </ul>\n          </div>\n          <div class=\"col-b\">\n            <section class=\"getinvolved\">\n              <h2 class=\"subhed\">写出来</h2>\n              <div class=\"task\" data-hashtag=\"#write\">\n                <p>不管你在twitter或者github有多少粉丝，把你学到的东西写出来！</p>\n                <a href=\"#\" class=\"pledge\">我要参与！</a>\n                <div class=\"pledges\"><p>下面是一些和你志同道合的开发者:</p></div>\n              </div>\n            </section>\n          </div>\n        </section>\n        <section id=\"filebugs\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">bugs归档</h1>\n            <p>其实，所有的浏览器厂商都希望你帮她们做好bugs归档，而不是在twitter上报告bug。</p>\n            <ul>\n              <li><a href=\"http://coding.smashingmagazine.com/2011/09/07/help-the-community-report-browser-bugs/\">帮助社区：提交浏览器Bugs</a> - Lea Verou</li>\n              <li><a href=\"http://ejohn.org/blog/a-web-developers-responsibility/\">一个web开发者的义务</a> - John Resig</li>\n              <li><a href=\"http://a11ybugs.org/\">处理浏览器无障碍相关的bugs</a> - Vlad Alexander</li>\n              <li>\n                <p>浏览器问题追踪 - 查找已经提交的bug或者提交新的bug：</p>\n                <ul class=\"resources\">\n                  <li><a href=\"https://bugzilla.mozilla.org/\">Mozilla's bugzilla</a></li>\n                  <li><a href=\"https://bugs.webkit.org/\">WebKit bugs</a></li>\n                  <li><a href=\"http://crbug.com/\">Chrome bugs</a></li>\n                  <li><a href=\"http://www.opera.com/support/bugs/\">Opera bugs</a></li>\n                  <li><a href=\"https://connect.microsoft.com/site/sitehome.aspx?SiteID=136\">Help IE</a></li>\n                </ul>\n              </li>\n            </ul>\n          </div>\n          <div class=\"col-b\">\n            <section class=\"getinvolved\">\n              <h2 class=\"subhed\">杜绝bug</h2>\n              <div class=\"task\" data-hashtag=\"#filebugs\">\n                <p>让浏览器变得更好的最快的方法，是给bug归档并解决这些bug。这只需要很少的时间，而且任何人都可以做。</p>\n                <a href=\"#\" class=\"pledge\">我要参与！</a>\n                <div class=\"pledges\"><p>下面是一些和你志同道合的开发者:</p></div>\n              </div>\n            </section>\n          </div>\n        </section>\n    </article>\n    <article class=\"section\">\n      <div class=\"standout\" id=virtuoso>\n        <h1 class=\"hed\">大家</h1>\n        <h2 class=\"subhed\">你已经身经百战、经验丰富！我们能再给你一些建议吗？</h2>\n      </div>\n      <section id=\"hack\" class=\"col-ab\">\n        <div class=\"col-a\">\n          <h1 class=\"hed\">Hack！</h1>\n          <p>把web的潜能发挥到极限！研究CSS、高级HTML、JavaScript。研究浏览器渲染引擎。在github上fork项目、研究其源码、不断学习。让我们把web变得更帅，通过各种各样的途径：</p>\n\n          <h2 id=\"contribute_to_browsers\" class=\"subhed\">为浏览器的发展贡献一己之力</h2>\n          <ul>\n            <li>帮助打造像<a href=\"http://trac.webkit.org/wiki/WebInspector\">WebKit Inspector</a>和<a href=\"https://github.com/operasoftware/dragonfly/\">Dragonfly</a>一样的开发工具。\n            他们是用HTML、CSS、和JS写的，所以你不需要懂C++也一样可以贡献自己的力量。开始动手吧！</li>\n            <li><a href=\"https://developer.mozilla.org/en/Gecko_BugAThon\">为Mozilla提供精简的测试用例</a></li>\n            <li>研究Gecko\n              <ul>\n                <li>阅读开发者指引：<a href=\"https://developer.mozilla.org/En/Developer_Guide\">Gecko开发入门</a>.\n                <li><a href=\"https://bugzilla.mozilla.org/buglist.cgi?quicksearch=%22[mentor%3D%22&list_id=1800469\">Firefox/Gecko的&#8220;good first bugs&#8221;列表</a>\n                <li>在<a href=\"#mozilla_irc\">Mozilla's IRC的服务器上</a>加入 #introduction 和 #developers。\n              </ul>\n            <li>研究Webkit\n              <ul>\n                <li><a href=\"http://dev.chromium.org/developers/contributing-to-webkit\">Google的怎么为WebKit添砖加瓦指引</a>\n              </ul>\n          </ul>\n\n          <h2 id=\"contribute_to_testsuites\" class=\"subhed\">贡献测试套件</h2>\n\n          <p>测试用例是标准和浏览器的基础，他们确保各种特性在所有浏览器中表现一致。然而，W3C现在的测试套件还没有达到他们需要的量。这些测试用web开发者所属性的语言写的：HTML、CSS、JavaScript。 </p>\n\n          <ul>\n            <li>去了解一下\n              <a href=\"http://www.w3.org/2008/webapps/wiki/Testing\">w3c webapps 测试套件</a>、\n              <a href=\"http://www.w3.org/html/wg/wiki/Testing\">w3c HTML5 测试套件</a>、\n              和 <a href=\"http://wiki.csswg.org/test\">CSSWG 测试套件</a>。\n            </li>\n            <li>到W3C测试套件中去研究一下<a href=\"http://www.w3.org/html/wg/wiki/Testing#New_tests\">最新的和已经有的测试</a>。</li>\n            <li>最新的<a href=\"http://trac.webkit.org/browser/trunk/LayoutTests\">WebKit&#8217;s LayoutTests</a>. <span>同时了解一下LayoutTests的<a href=\"http://www.webkit.org/blog/1452/layout-tests-theory/\">原理</a>和<a href=\"http://www.webkit.org/blog/1456/layout-tests-practice/\">实践</a>。</span></li>\n            <li>最新的<a href=\"https://developer.mozilla.org/en/Mochitest\">Mozilla&#8217;s Mochitests</a>。</li>\n            <li>加入讨论<a href=\"http://lists.w3.org/Archives/Public/public-webapps-testsuite/\">public-webapps-testsuite</a>、<a href=\"http://lists.w3.org/Archives/Public/public-html-testsuite/\">public-html-testsuite</a>、和<a href=\"http://lists.w3.org/Archives/Public/public-css-testsuite/\">public-css-testsuite</a>的邮件列表。</li>\n            <li>参与HTML5 Audio相关的<a href=\"http://areweplayingyet.org\">AreWePlayingYet?测试套件</a>。</li>\n          </ul>\n\n          <h2 id=\"contribute_to_specs\" class=\"subhed\">帮助完善规范</h2>\n          <ul>\n            <li>评审<a href=\"http://www.w3.org/Bugs/Public/\">W3C bugzilla</a>上已经存在的bugs <span>- 并学习 <a href=\"http://wiki.whatwg.org/wiki/Bugzilla_conventions\">Bugzilla公约</a>。</span>\n            <li>参与<a href=\"http://www.whatwg.org/mailing-list\">WHATWG</a> / <a href=\"http://lists.w3.org/Archives/Public/public-webapps/\">public-webapps</a> / <a href=\"http://lists.w3.org/Archives/Public/www-style/\">www-style</a> / <a href=\"http://lists.w3.org/Archives/Public/public-fx/\">public-fx</a> 的讨论。</li>\n            <li><a href=\"http://dev.chromium.org/developers/how-tos/make-a-web-standards-proposal\">做一份web标准提案</a>。 <span>（这份指引告诉你怎么去做）</span>\n            <li><a href=\"http://wiki.whatwg.org/wiki/How_to_write_a_spec\">编写规范！</a> <span>我们需要更多的规范编写者。</span></li>\n          </ul>\n\n          <h2 id=\"contribute_to_validators\" class=\"subhed\">为验证做贡献</h2>\n          <ul>\n            <li>\n              <a href=\"http://validator.nu/\">HTML验证</a> <span>需要Java开发人员，详情请看<a href=\"https://github.com/h5bp/lazyweb-requests/issues/18\">lazyweb-reqs/18</a></span>\n            <li>\n              <a href=\"http://lists.w3.org/Archives/Public/www-validator-css/\">CSS验证</a> <span>订阅这个邮件列表，里面总是需要各种帮助。</span>\n            <li>\n              <a href=\"https://bitbucket.org/annevk/webvtt\">WebVTT</a> <span>一种视频字幕格式。</span>\n          </ul>\n        </div>\n        <div class=\"col-b\">\n          <section class=\"getinvolved\">\n\t\t\t<h2 class=\"subhed\">置身代码</h2>\n            <div class=\"task\" data-hashtag=\"#hack\">\n              <p>书写你的代码。不断试验、在github上fork项目、深入源码。为浏览器、规范、验证或一些不错的<a href=\"#open_source_projects_worth_your_time\">开源项目</a>提供帮助！</p>\n              <a href=\"#\" class=\"pledge\">我要参与！</a>\n              <div class=\"pledges\"><p>下面是一些和你志同道合的开发者:</p></div>\n            </div>\n          </section>\n        </div>\n      </section>\n    </article>\n\n    <footer class=\"doc\">\n      <p class=\"subhed summary\">\n        你可以让web变成你期望的那样。浏览器厂商、标准编撰者、框架/类库的作者在等待你的反馈和参与。<br>我们共同努力就可以推动web不断地向前发展。\n      </p>\n\n      <img src=\"../img/pugerton.png\" alt=\"Pugerton\">\n\n      <p class=\"subhed\">这是以下诸位爱与泪的结晶</p>\n\n      <ul class=\"builders\">\n          <li><a href=\"https://twitter.com/wilto\"><img src=\"https://pbs.twimg.com/profile_images/477441227986444289/KHCUqTis_normal.png\" alt=\"Mat Marquis\"> <b>Mat</b> Marquis</a>\n          <li><a href=\"https://twitter.com/aaronforsander\"><img src=\"https://pbs.twimg.com/profile_images/461528075788763138/c7ONSIRm_normal.jpeg\" alt=\"Aaron Forsander\"> <b>Aaron</b> Forsander</a>\n          <li><a href=\"https://twitter.com/connor\"><img src=\"https://pbs.twimg.com/profile_images/526185574039031808/IpDbRAX5_normal.jpeg\" alt=\"Connor Montgomery\"> <b>Connor Montgomery</b></a>\n          <li><a href=\"https://twitter.com/paul_irish\"><img src=\"https://pbs.twimg.com/profile_images/420826194083213312/CP1RmLa3_normal.jpeg\" alt=\"Paul Irish\"> <b>Paul</b> Irish</a>\n          <li><a href=\"https://twitter.com/divya\"><img src=\"https://pbs.twimg.com/profile_images/550530231853776897/kni4F8oM_normal.png\" alt=\"Diviya Manian\"> <b>Divya</b> Manian</a>\n          <li><a href=\"https://twitter.com/necolas\"><img src=\"https://pbs.twimg.com/profile_images/529444560179449857/eKdCJhvp_normal.jpeg\" alt=\"Nicolas Gallagher\"> <b>Nicolas</b> Gallagher</a>\n          <li><a href=\"https://twitter.com/addyosmani\"><img src=\"https://pbs.twimg.com/profile_images/422476220442234880/jlx9HMtr_normal.jpeg\" alt=\"Addy Osmani\"> <b>Addy</b> Osmani</a>\n      </ul>\n      <p class=\"others\">还有<a href=\"https://github.com/h5bp/movethewebforward/contributors\"><span>所有这些可敬的人儿</span>。</a></p>\n      <p>恐龙插画由<a href=\"http://dribbble.com/deathbearbrown\">Sue Lockwood</a>提供 • <a href=\"https://github.com/h5bp/movethewebforward\">Contribute to this project!</a></p>\n    </footer>\n    <!-- script>\n        window._gaq=[['_setAccount','UA-17904194-2'],['_trackPageview']];\n        (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];\n        g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';\n        s.parentNode.insertBefore(g,s)}(document,'script'));\n    </script -->\n</body>\n</html>\n"
  },
  {
    "path": "combine.php",
    "content": "<?php\n\n\t/************************************************************************\n\t * CSS and Javascript Combinator 0.5\n\t * Copyright 2006 by Niels Leenheer\n\t *\n\t * Permission is hereby granted, free of charge, to any person obtaining\n\t * a copy of this software and associated documentation files (the\n\t * \"Software\"), to deal in the Software without restriction, including\n\t * without limitation the rights to use, copy, modify, merge, publish,\n\t * distribute, sublicense, and/or sell copies of the Software, and to\n\t * permit persons to whom the Software is furnished to do so, subject to\n\t * the following conditions:\n\t * \n\t * The above copyright notice and this permission notice shall be\n\t * included in all copies or substantial portions of the Software.\n\t *\n\t * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n\t * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n\t * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n\t * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n\t * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n\t * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n\t * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\t */\n\n\n\t$cache \t  = false;\n\t$cachedir = dirname(__FILE__) . '/cache';\n\t$cssdir   = dirname(__FILE__) . '/css';\n\t$jsdir    = dirname(__FILE__) . '/js';\n\n\t// Determine the directory and type we should use\n\tswitch ($_GET['type']) {\n\t\tcase 'css':\n\t\t\t$base = realpath($cssdir);\n\t\t\tbreak;\n\t\tcase 'javascript':\n\t\t\t$base = realpath($jsdir);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\theader (\"HTTP/1.0 503 Not Implemented\");\n\t\t\texit;\n\t};\n\n\t$type = $_GET['type'];\n\t$elements = explode(',', $_GET['files']);\n\t\n\t// Determine last modification date of the files\n\t$lastmodified = 0;\n\twhile (list(,$element) = each($elements)) {\n\t\t$path = realpath($base . '/' . $element);\n\t\t\n\t\tif (($type == 'javascript' && substr($path, -3) != '.js') || \n\t\t\t($type == 'css' && substr($path, -4) != '.css')) {\n\t\t//\theader (\"HTTP/1.0 403 Forbidden\");\n\t\t\texit;\t\n\t\t}\n\t\n\t\tif (substr($path, 0, strlen($base)) != $base || !file_exists($path)) {\n\t\t\theader (\"HTTP/1.0 404 Not Found\");\n\t\t\texit;\n\t\t}\n\t\t\n\t\t$lastmodified = max($lastmodified, filemtime($path));\n\t}\n\t\n\t// Send Etag hash\n\t$hash = $lastmodified . '-' . md5($_GET['files']);\n\theader (\"Etag: \\\"\" . $hash . \"\\\"\");\n\t\n\tif (isset($_SERVER['HTTP_IF_NONE_MATCH']) && \n\t\tstripslashes($_SERVER['HTTP_IF_NONE_MATCH']) == '\"' . $hash . '\"') \n\t{\n\t\t// Return visit and no modifications, so do not send anything\n\t\theader (\"HTTP/1.0 304 Not Modified\");\n\t\theader ('Content-Length: 0');\n\t} \n\telse \n\t{\n\t\t// First time visit or files were modified\n\t\tif ($cache) \n\t\t{\n\t\t\t// Determine supported compression method\n\t\t\t$gzip = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip');\n\t\t\t$deflate = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate');\n\t\n\t\t\t// Determine used compression method\n\t\t\t$encoding = $gzip ? 'gzip' : ($deflate ? 'deflate' : 'none');\n\t\n\t\t\t// Check for buggy versions of Internet Explorer\n\t\t\tif (!strstr($_SERVER['HTTP_USER_AGENT'], 'Opera') && \n\t\t\t\tpreg_match('/^Mozilla\\/4\\.0 \\(compatible; MSIE ([0-9]\\.[0-9])/i', $_SERVER['HTTP_USER_AGENT'], $matches)) {\n\t\t\t\t$version = floatval($matches[1]);\n\t\t\t\t\n\t\t\t\tif ($version < 6)\n\t\t\t\t\t$encoding = 'none';\n\t\t\t\t\t\n\t\t\t\tif ($version == 6 && !strstr($_SERVER['HTTP_USER_AGENT'], 'EV1')) \n\t\t\t\t\t$encoding = 'none';\n\t\t\t}\n\t\t\t\n\t\t\t// Try the cache first to see if the combined files were already generated\n\t\t\t$cachefile = 'cache-' . $hash . '.' . $type . ($encoding != 'none' ? '.' . $encoding : '');\n\t\t\t\n\t\t\tif (file_exists($cachedir . '/' . $cachefile)) {\n\t\t\t\tif ($fp = fopen($cachedir . '/' . $cachefile, 'rb')) {\n\n\t\t\t\t\tif ($encoding != 'none') {\n\t\t\t\t\t\theader (\"Content-Encoding: \" . $encoding);\n\t\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\theader (\"Content-Type: text/\" . $type);\n\t\t\t\t\theader (\"Content-Length: \" . filesize($cachedir . '/' . $cachefile));\n\t\t\n\t\t\t\t\tfpassthru($fp);\n\t\t\t\t\tfclose($fp);\n\t\t\t\t\texit;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\n\t\t// Get contents of the files\n\t\t$contents = '';\n\t\treset($elements);\n\t\twhile (list(,$element) = each($elements)) {\n\t\t\t$path = realpath($base . '/' . $element);\n\t\t\t$contents .= \"\\n\\n\" . file_get_contents($path);\n\t\t}\n\t\n\t\t// Send Content-Type\n\t\theader (\"Content-Type: text/\" . $type);\n\t\t\n\t\tif (isset($encoding) && $encoding != 'none') \n\t\t{\n\t\t\t// Send compressed contents\n\t\t\t$contents = gzencode($contents, 9, $gzip ? FORCE_GZIP : FORCE_DEFLATE);\n\t\t\theader (\"Content-Encoding: \" . $encoding);\n\t\t\theader ('Content-Length: ' . strlen($contents));\n\t\t\techo $contents;\n\t\t} \n\t\telse \n\t\t{\n\t\t\t// Send regular contents\n\t\t\theader ('Content-Length: ' . strlen($contents));\n\t\t\techo $contents;\n\t\t}\n\n\t\t// Store cache\n\t\tif ($cache) {\n\t\t\tif ($fp = fopen($cachedir . '/' . $cachefile, 'wb')) {\n\t\t\t\tfwrite($fp, $contents);\n\t\t\t\tfclose($fp);\n\t\t\t}\n\t\t}\n\t}\t\n"
  },
  {
    "path": "crossdomain.xml",
    "content": "<?xml version=\"1.0\"?>\n<!DOCTYPE cross-domain-policy SYSTEM \"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\">\n<cross-domain-policy>\n\n\n<!-- Read this: www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html -->\n\n<!-- Most restrictive policy: -->\n\t<site-control permitted-cross-domain-policies=\"none\"/>\n\n\n\n<!-- Least restrictive policy: -->\n<!--\n\t<site-control permitted-cross-domain-policies=\"all\"/>\n\t<allow-access-from domain=\"*\" to-ports=\"*\" secure=\"false\"/>\n\t<allow-http-request-headers-from domain=\"*\" headers=\"*\" secure=\"false\"/>\n-->\n<!--\n  If you host a crossdomain.xml file with allow-access-from domain=\"*\"\n  and don’t understand all of the points described here, you probably\n  have a nasty security vulnerability. ~ simon willison\n-->\n\n</cross-domain-policy>\n"
  },
  {
    "path": "css/fonts.css",
    "content": "@font-face { font-family: 'Adelle'; src: url('fonts/adelle_reg-webfont.eot'); src: url('fonts/adelle_reg-webfont.eot?#iefix') format('embedded-opentype'), url('fonts/adelle_reg-webfont.woff') format('woff'), url('fonts/adelle_reg-webfont.ttf') format('truetype'), url('fonts/adelle_reg-webfont.svg#AdelleRegular') format('svg'); font-weight: normal; font-style: normal; }\n\n@font-face { font-family: 'ChunkFive'; src: url('fonts/chunkfive-webfont.eot'); src: url('fonts/chunkfive-webfont.eot?#iefix') format('embedded-opentype'), url('fonts/chunkfive-webfont.woff') format('woff'), url('fonts/fonts/chunkfive-webfont.ttf') format('truetype'), url('fonts/chunkfive-webfont.svg#ChunkFiveRoman') format('svg'); font-weight: normal; font-style: normal; }\n\n"
  },
  {
    "path": "css/img/.gitignore",
    "content": "!.gitignore\n\n"
  },
  {
    "path": "css/style.css",
    "content": "/*\n * the HTML5✰Boilerplate css, natch.\n */\n\narticle,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}[hidden]{display:none}html{font-size:100%;overflow-y:scroll;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0;font-size:1em;line-height:1.4}body,button,input,select,textarea{font-family:sans-serif;color:#222}a{color:#00e}a:visited{color:#551a8b}a:hover{color:#06e}a:focus{outline:thin dotted}a:hover,a:active{outline:0}abbr[title]{border-bottom:1px dotted;cursor:help}blockquote{margin:1em 40px}dfn{font-style:italic}hr{display:block;height:1px;border:0;border-top:1px solid #ccc;margin:1em 0;padding:0}ins{background:#ff9;color:#000;text-decoration:none}mark{background:#ff0;color:#000;font-style:italic;font-weight:bold}pre,code,kbd,samp{font-family:monospace,serif;_font-family:'courier new',monospace;font-size:1em}pre{white-space:pre;white-space:pre-wrap;word-wrap:break-word}q{quotes:none}\nq:before,q:after{content:\"\";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}ul,ol{margin:1em 0;padding:0 0 0 40px}dd{margin:0 0 0 40px}nav ul,nav ol{list-style:none;list-style-image:none;margin:0;padding:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:0;margin:0;padding:0}label{cursor:pointer}legend{border:0;*margin-left:-7px;padding:0}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=\"button\"],input[type=\"reset\"],input[type=\"submit\"]{cursor:pointer;-webkit-appearance:button;*overflow:visible}input[type=\"checkbox\"],input[type=\"radio\"]{box-sizing:border-box;padding:0}input[type=\"search\"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=\"search\"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top;resize:vertical}input:invalid,textarea:invalid{background-color:#f0dddd}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}\n\n::-moz-selection{ background:#73abf4;color:#fff;text-shadow:none; }\n::selection     { background:#73abf4;color:#fff;text-shadow:none; }\n\nh2::-moz-selection, h3::-moz-selection{ color:#333;}\nh2::selection,      h3::selection     { color:#333;}\n\n\n/* =============================================================================\n   Site styles\n   ========================================================================== */\nimg {\n\tmax-width: 100%;\n}\n.resources {\n    overflow: auto;\n    list-style: none;\n    padding: 1.18em 0 0 0;\n    font-size: .9em;\n}\n.task ul,\n.resources ul {\n    list-style: none;\n    padding: .25em 0 .4em 1.2em;\n}\n.task li,\n.resources li {\n    padding: .2em 0;\n}\n.task li:before,\n.resources > li:before {\n    color: #3d526d;\n    content: \"■\";\n    float: left;\n    font-size: .85em;\n    padding: .1em .6em 0 0;\n}\n.resources li li {\n    padding: 0;\n}\n.resources li p {\n    margin: 0;\n    line-height: 1.5;\n}\n.resources ul a {\n    border-radius: 3px;\n    display: inline-block;\n    margin-left: -8px;\n    padding: 1px 5px 0 5px;\n}\n\nbody {\n    background: #e7ebf1;\n    color: #525a64;\n    font: 100%/1.5 \"Adelle\", georgia, serif;\n}\n\nul, ol, blockquote {\n    margin: 0;\n    padding: 0 0 0 1.875%;\n}\n\nul li { padding: .2em 0; }\nh1, h2 { font-weight: normal; }\n\nblockquote {\n    border-left: 3px solid #5e7087;\n    font-style: italic;\n}\n\na, a:visited {\n    color: #4b73a6;\n    text-decoration: none;\n    -webkit-transition: color .1s linear;\n    -moz-transition: color .1s linear;\n    -ms-transition: color .1s linear;\n    -o-transition: color .1s linear;\n    transition: color .1s linear;\n}\n\na:hover, a:focus, a:active { color: #0c4c9d; }\n\n\n.resources ul a {\n    border-radius: 3px;\n    display: inline-block;\n    margin-left: -8px;\n    padding: 1px 5px 0 5px;\n}\n\np, .col-ab p { line-height: 1.65; }\n\n\nsection, header {\n    max-width: 990px;\n    margin: 0 auto;\n}\n\n.col-ab {\n    clear: both;\n\toverflow: auto;\n    padding: 0 2.9296875%;\n}\n\n.hed {\n    border-bottom: 1px solid #cbd1d8;\n    color: #324a69;\n    clear: both;\n    float: left;\n    font: normal 1.8em/1.2 \"ChunkFive\", arial, helvetica, sans-serif;\n    letter-spacing: -.02em;\n    margin: 0 0 .5em 0;\n    padding: .5em 0 .1em 0;\n    text-shadow: 1px 1px 0 rgba(255,255,255,.8);\n    width: 100%;\n}\n\n.no-fontface .hed { font-weight: bold; }\n\n.subhed {\n    color: #7f8c9c;\n    font: normal 1.4em/1 \"ChunkFive\", georgia, serif;\n    margin: 1em 0 0 0;\n    text-shadow: 1px 1px 0 rgba(255,255,255,.8);\n}\n\n.col-b .subhed { margin-top: 2em; }\n\n.standout {\n    background: #687482 url(/css/img/bg_noise.png) 0 0 repeat;\n    background-origin: padding;\n    border: double #494f57;\n    border-width: 3px 0;\n\n    background:\n        url(/css/img/bg_noise.png) 0 0 repeat,\n        -moz-radial-gradient(center top, ellipse farthest-corner, #7f8c96, #687482 38%);\n    background:\n        url(/css/img/bg_noise.png) 0 0 repeat,\n        -webkit-radial-gradient(center top, ellipse farthest-corner, #7f8c96, #687482 38%);\n    background:\n        url(/css/img/bg_noise.png) 0 0 repeat,\n        -o-radial-gradient(center top, ellipse farthest-corner, #7f8c96, #687482 38%);\n    background:\n        url(/css/img/bg_noise.png) 0 0 repeat,\n        -ms-radial-gradient(center top, ellipse farthest-corner, #7f8c96, #687482 38%);\n    background:\n        url(/css/img/bg_noise.png) 0 0 repeat,\n        radial-gradient(center top, ellipse farthest-corner, #7f8c96, #687482 38%);\n\n    clear: both;\n    margin: 3.5em 0 2em 0;\n    padding: 1em 2.9296875% 0 2.9296875%;\n    box-shadow: inset 0 0 10px #5d6672;\n}\n.oldie .standout {\n    background: #687482;\n}\n\n.standout .subhed,\n.doc-hed {\n    color: #b5c5d7;\n    font: 1.5em/1 \"ChunkFive\", georgia, serif;\n    letter-spacing: .05em;\n    margin: 0;\n    padding: .2em 0 .8em 0;\n    text-align: center;\n    text-shadow: #494f57 1px 1px, #494f57 2px 2px;\n}\n.standout .hed {\n    border: none;\n    color: #e0e6ed;\n    float: none;\n    font-size: 2.6em;\n    letter-spacing: 0;\n    line-height: 1;\n    margin: 0;\n    padding: 0;\n    text-align: center;\n    text-shadow: #494f57 1px 1px, #494f57 2px 2px;\n}\n.no-fontface .standout .hed {\n    font-weight: bold;\n    padding: 0 0 .25em 0;\n}\n.no-fontface .standout .subhed { letter-spacing: normal; }\n\n.doc-hed {\n    display: block;\n    width: 100%;\n    padding: .8em 0 0 0;\n    text-align: left;\n    text-shadow: #494f57 1px 1px, #494f57 2px 2px;\n}\n\n.doc-hed b,\n.doc-hed .hed {\n\tdisplay: block;\n    line-height: 1;\n    margin: 0 0 .05em 0;\n    padding: 0;\n    text-align: left;\n    text-shadow: #494f57 1px 1px, #494f57 2px 2px, #494f57 3px 3px;\n    width: 100%;\n}\n\n\n.lead {\n    text-align: center;\n    margin-bottom: .25em;\n    padding: 0 0 1em 0;\n}\nbody {\n    border-top: .2em solid indianred;\n}\n\n.hed-lead {\n    background-size: 100% auto;\n    background: url(/css/img/webasaurs.gif) center 0 no-repeat;\n    color: #324a69;\n    font: 2.4em/1 \"ChunkFive\", arial, helvetica, sans-serif;\n    margin: 5% 0 0 0;\n    padding: 25% 0 .25em 0;\n    text-shadow: 1px 1px 0 #fff;\n    position:relative;\n}\n\n.lead .hed-lead span {\n    background: url(/css/img/beanie-webasaurs.gif) center 0 no-repeat;\n    opacity: 0;\n    display:block; \n    background-size: 100% auto;\n    position: absolute;\n    left: 0; top: 0;\n    height: 100%;\n    width: 100%;\n\n    -webkit-transition: all 0.3s ease-out;  \n       -moz-transition: all 0.3s ease-out;  \n        -ms-transition: all 0.3s ease-out;  \n         -o-transition: all 0.3s ease-out;  \n            transition: all 0.3s ease-out;\n    *display: none; /* hide from IE6/7, looking a bit broken */\n    \n}\n/* no hover hats \n.lead .hed-lead:hover span {\n\topacity: 1;\n}\n*/\n.no-fontface .hed-lead {\n    font-weight: bold;\n    letter-spacing: -1px;\n}\n.subhed-lead {\n    color: #5d6474;\n    font: normal 1.6em/1 \"ChunkFive\", georgia, serif;\n\tmargin: 0 0 1.25em 0;\n    padding: 0 .5em;\n    text-shadow: 1px 1px 0 #fff;\n}\n.lead .subhed, p.summary {\n\tline-height: 1.3em;\n\tmargin: .85em auto 0;\n\tpadding: .8em 10%;\n}\n.lead .subhed b {\n\tpadding-top: .5em;\n\tdisplay: block;\n}\n\n.lead p, p.summary {\n  padding: 1em 0;\n  margin-top: 2em;\n  border: 2px double #7f8c9c;\n  border-width: 4px 0;\n}\n\np.summary {\n  max-width: 840px;\n  margin-bottom: 70px;\n}\n\n.lead p b { color: #5d6474; }\n\n.section > section { margin-top: 2em; }\n\n.col-ab ul {\n    font-size: .9em;\n    margin-top: .9em;\n    list-style: none;\n    padding: .1em 0 0 0;\n}\n\n\n/* Nav Sticky */\n.sticky { \n  position: fixed; \n  left: 0; \n  z-index: 2; \n  margin: 0; \n\n  -webkit-transition:all 0.3s ease-in-out;\n     -moz-transition:all 0.3s ease-in-out;\n      -ms-transition:all 0.3s ease-in-out;\n       -o-transition:all 0.3s ease-in-out;\n          transition:all 0.3s ease-in-out;\n}\n\nsection ul, section ol {\n    margin-left: 2%;\n}\n\n.col-ab li { padding: 0.5em 0; }\n\n.col-ab li > ul > li { padding-left: 2em; }\n\n.col-ab li:not(:last-child) { border-bottom: 1px dotted #bfc6cf; }\n.col-ab li > ul > li:not(:last-child) { border-bottom: 0; }\n\n/* Get Involved Sidebar */\n.getinvolved { font-size: 0.9em; }\n\n.pledge, .pledge:visited {\n  display: inline-block;\n  width: 90%;\n  padding: .6em 5% .5em 5%;\n  background: #435772;\n  text-shadow: 1px 1px 1px #000;\n  color: #fff;\n  text-align: center;\n  border-radius: 5px;\n  box-shadow: 1px 1px 2px #000;\n  margin-bottom: 1em;\n  -webkit-transition: background 0.3s ease-out;\n     -moz-transition: background 0.3s ease-out;\n      -ms-transition: background 0.3s ease-out;\n       -o-transition: background 0.3s ease-out;\n          transition: background 0.3s ease-out;\n}\n.pledge:hover {\n\tbackground: #294160;\n\tcolor: #fff;\n}\n\n/* Twitter Avatar Styles */\n.pledges { padding-top: .5em; }\n\n.pledges a {\n    display: inline-block;\n    margin: .15em;\n}\n.pledges img { max-width: 25px; }\n.pledges p { display: none; }\n\n.tasks {\n    font-size: .9em;\n    margin-top: .9em;\n    padding: .1em 0 0 0;\n    margin-left: 0;\n}\n\nul.tasks { list-style: none; }\n\nol.tasks { list-style-position: inside; }\n\n.tasks p { margin: .5em 0 0 0; }\n\n.resources {\n    overflow: auto;\n    list-style: none;\n    padding: 1.18em 0 0 0;\n    font-size: .9em;\n}\n\n.task ul,\n.resources ul {\n    list-style: none;\n    padding: .25em 0 .4em 1.2em;\n}\n.task li,\n.resources li {\n    padding: .2em 0;\n}\n.task li:before,\n.resources > li:before {\n    color: #3d526d;\n    content: \"■\";\n    float: left;\n    font-size: .85em;\n    padding: .1em .6em 0 0;\n}\n.resources li li {\n    padding: 0;\n}\n.resources li p {\n    margin: 0;\n    line-height: 1.5;\n}\n.resources ul a {\n    border-radius: 3px;\n    display: inline-block;\n    margin-left: -8px;\n    padding: 1px 5px 0 5px;\n}\n\nli span { opacity: 0;\n  -webkit-transition: opacity 0.3s ease-out;\n     -moz-transition: opacity 0.3s ease-out;\n      -ms-transition: opacity 0.3s ease-out;\n       -o-transition: opacity 0.3s ease-out;\n          transition: opacity 0.3s ease-out;\n}\nli:hover > span, .touch li > span { opacity: 1;}\n\nnav {\n  text-align: center;\n  background: rgb(50, 74, 105);\n  background: -o-linear-gradient(rgba(50, 74, 105, 0.8), rgba(50, 74, 105, 1));\n  background: -webkit-linear-gradient(rgba(50, 74, 105, 0.8), rgba(50, 74, 105, 1));\n  background: -moz-linear-gradient(rgba(50, 74, 105, 0.8), rgba(50, 74, 105, 1));\n  background: -ms-linear-gradient(rgba(50, 74, 105, 0.8), rgba(50, 74, 105, 1));\n  width: 100%;\n  margin: 2em 0 0;\n  box-shadow: 0 1px 3px rgba(0,0,0,.2);\n}\n\nnav ul,\nnav ol {\n    display: table;\n    width: 100%;\n    padding: 0;\n    border-bottom: 0.2em solid indianred;\n}\n\nnav li {\n    padding: 0;\n    display: table-cell;\n    *display: inline;\n    *zoom: 1;\n    *padding: 0 40px;\n}\n\nnav a, nav a:visited { \n    color: rgb(231, 235, 241);\n    text-shadow: 0 1px #000;\n    padding: .6em 0 .5em 0;   \n    display: block;\n    font-weight: bold;\n    -webkit-transition: background 0.3s ease-out;\n       -moz-transition: background 0.3s ease-out;\n        -ms-transition: background 0.3s ease-out;\n         -o-transition: background 0.3s ease-out;\n            transition: background 0.3s ease-out;\n            \n}\nnav a:hover, nav a:focus, nav a.active {\n    color: #fff;\n    background: -moz-radial-gradient(center bottom, ellipse cover,  rgba(255,255,255,.4) 0%, rgba(50, 74, 105,0) 40%);\n    background: -webkit-radial-gradient(center bottom, ellipse cover,  rgba(255,255,255,.4) 0%,rgba(50, 74, 105,0) 40%);\n    background: -o-radial-gradient(center bottom, ellipse cover,  rgba(255,255,255,.4) 0%,rgba(50, 74, 105,0) 40%);\n    background: -ms-radial-gradient(center bottom, ellipse cover,  rgba(255,255,255,.4) 0%,rgba(50, 74, 105,0) 40%);\n    background: radial-gradient(center bottom, ellipse cover,  rgba(255,255,255,.4) 0%,rgba(50, 74, 105,0) 40%);\n}\n\n\nnav li:not(:last-child) { border-bottom: 0; }\n\n.col-ab {\n    clear: both;\n    padding: 0 2.9296875%;\n}\n\n.col-a {\n    position: relative;\n}\n\nfooter.doc {\n  text-align: center;\n  font-size: 0.8em;\n  padding: 3em;\n}\n\nfooter.doc .others { font-size: 1.5em; }\n\nimg[alt=Pugerton] { display: none; }\n\n.builders {\n    text-align: center;\n    margin: 2em auto 2em auto;\n    max-width: 750px;\n}\n.builders li {\n    list-style: none;\n    display: inline;\n}\n\n.builders a {\n    display: inline-block;\n    padding: 0.5em 0 0.5em 0.5em;\n    min-height: 48px;\n    margin: 5px 0;\n    width: 150px;\n    text-align: left;\n}\n\n.builders a img { float: left; margin-right: 1em; border-radius: 5px; }\n\n.builders a b { display: block; font-weight: normal; }\n\n\n@media screen and (min-width: 800px) {\n  .gimmick i {\n    position: fixed;\n    top: 0;\n    right: 5%;\n    display: block;\n\t\twidth:0px;\n\t\theight:0px;\n\t\tz-index: -1;\n\t\topacity: 0;\n\t\tborder-left: 200px solid transparent;\n\t\tborder-right: 200px solid transparent;\n\t\tborder-top: 200px solid #d7dde8;\n\t\tborder-top: 200px solid rgba(181, 197, 215, 0.5);\n\t\tmargin-right: -55px;\n  }\n  \n  .gimmick i + i {\n    top: 100px;\n\t\tborder-left:200px solid transparent;\n\t\tborder-right:200px solid transparent;\n\t\tborder-top: 200px solid #d7dde8;\n\t\tborder-top:200px solid rgba(181, 197, 215, 0.5);\n  }\n  \n  .gimmick i:last-child {\n    top: 200px;\n    margin-right: -20px;\n\t\tborder-left: 100px solid transparent;\n\t\tborder-right: 100px solid transparent;\n\t\tborder-top: 100px solid #CD5B5B;\n\t\tborder-top:100px solid hsla(0, 53%, 58%, 0.5);\n  }  \n  \n  .oldie .gimmick {\n\t\t_display: none;\n  }\n\n  .col-a {\n\t\tfloat: left;\n\t\twidth: 68.607068607069%;\n\t}\n\n  .col-b {\n\t\twidth: 25.155925155925%;\n\t\tfloat: right;\n\t}\n\n  .col-ab p {\n        max-width: 950px;\n        line-height: 1.5;\n    }\n\n   .hed-lead {\n        font: 3.625em/1 \"ChunkFive\", georgia, serif;\n\t    margin: 2% 0 .1em 0;\n\t    padding: 22% 0 0 0;\n    }\n\t.subhed-lead {\n        font-size: 2.2em;\n\t}\n\t.lead .subhed b {\n\t\tdisplay: inline;\n\t\tpadding: 0;\n    font-weight: normal;\n\t}\n    .lead p {\n        max-width: 9999px;\n    }\n\n    .hed {\n        font: normal 2.4em/1.2 \"ChunkFive\", arial, helvetica, sans-serif;\n    }\n\n    .standout .hed {\n        font-size: 4.8em;\n    }\n\n    .standout .subhed,\n    .doc-hed {\n        font: 2em/1 \"ChunkFive\", georgia, serif;\n    }\n\n    .col-split {\n        padding-top: 1em;\n        -webkit-column-count: 2;\n        -webkit-column-gap: 2.079002079002%;\n        -moz-column-count: 2;\n        -moz-column-gap: 2.079002079002%;\n        -ms-column-count: 2;\n        -ms-column-gap: 2.079002079002%;\n        column-count: 2;\n        column-gap: 2.079002079002%;\n    }\n    .col-split p {\n        padding: 0 0 1em 0;\n        margin: 0;\n        -webkit-break-after: column;\n        -moz-break-after: column;\n        break-after: column;\n    }\n\n\t.col-split {\n\t\tpadding-top: 1em;\n\t\t-webkit-column-count: 2;\n\t\t-webkit-column-gap: 2.079002079002%;\n\t\t-moz-column-count: 2;\n\t\t-moz-column-gap: 2.079002079002%;\n\t\t-ms-column-count: 2;\n\t\t-ms-column-gap: 2.079002079002%;\n\t\t-o-column-count: 2;\n\t\t-o-column-gap: 2.079002079002%;\n\t\tcolumn-count: 2;\n\t\tcolumn-gap: 2.079002079002%;\n\t}\n\t.col-split p {\n\t\tpadding: 0 0 1em 0;\n\t\tmargin: 0;\n\t}\n}\n\n\n/* =============================================================================\n   Helper classes\n   Please define your styles before this section.\n   ========================================================================== */\n\n\n.hidden { display: none !important; visibility: hidden; }\n\n.a11y-only { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }\n\n.a11y-only.focusable:active, .a11y-only.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; }\n\n.hide { visibility: hidden; }\n\n.clearfix:before, .clearfix:after,\n.section > section:before,\n.section > section:after { content: \"\"; display: table; }\n.clearfix:after,\n.section > section:after { clear: both; }\n.clearfix { *zoom: 1; }\n\n\n\n/* =============================================================================\n   Print styles\n   ========================================================================== */\n\n@media print {\n  * { background: transparent !important; color: black !important; box-shadow:none !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; } /* Black prints faster: h5bp.com/s */\n  a, a:visited { text-decoration: underline; }\n  a[href]:after { content: \" (\" attr(href) \")\"; }\n  abbr[title]:after { content: \" (\" attr(title) \")\"; }\n  .ir a:after, a[href^=\"javascript:\"]:after, a[href^=\"#\"]:after { content: \"\"; }  /* Don't show links for images, or javascript/internal links */\n  pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }\n  thead { display: table-header-group; } /* h5bp.com/t */\n  tr, img { page-break-inside: avoid; }\n  img { max-width: 100% !important; }\n  @page { margin: 0.5cm; }\n  p, h2, h3 { orphans: 3; widows: 3; }\n  h2, h3 { page-break-after: avoid; }\n}\n"
  },
  {
    "path": "humans.txt",
    "content": "/* the humans responsible & colophon */\n/* humanstxt.org */\n\n\n/* TEAM */\n  Aaron Forsander\n  Twitter: @aaronforsander\n  Location: United States of America\n\n  Addy Osmani\n  Twitter: @addyosmani\n  Location: United Kingdom\n\n  Connor Montgomery\n  Twitter: @c_t_montgomery\n  Location: United States of Americana\n\n  Divya Manian\n  Twitter: @divya\n  Location: United States of America\n\n  Mat Marquis\n  Twitter: @wilto\n  Location: United States of America\n\n  Mathias Bynens\n  Twitter: @mathias\n  Location: Belgium\n\n  Paul Irish\n  Twitter: @paul_irish\n  Location: United States of America\n\n\n/* THANKS */\n  Alexis Deveria\n  Daniel Filho\n  Dain Kennison\n  Ryan Olson\n  Nicolas Gallagher\n\n  More here: https://github.com/h5bp/movethewebforward/contributors\n\n\n/* SITE */\n  Standards: HTML5, CSS3\n  Components: Modernizr, jQuery\n  Software:\n\n\n\n                               -o/-\n                               +oo//-\n                              :ooo+//:\n                             -ooooo///-\n                             /oooooo//:\n                            :ooooooo+//-\n                           -+oooooooo///-\n           -://////////////+oooooooooo++////////////::\n            :+ooooooooooooooooooooooooooooooooooooo+:::-\n              -/+ooooooooooooooooooooooooooooooo+/::////:-\n                -:+oooooooooooooooooooooooooooo/::///////:-\n                  --/+ooooooooooooooooooooo+::://////:-\n                     -:+ooooooooooooooooo+:://////:--\n                       /ooooooooooooooooo+//////:-\n                      -ooooooooooooooooooo////-\n                      /ooooooooo+oooooooooo//:\n                     :ooooooo+/::/+oooooooo+//-\n                    -oooooo/::///////+oooooo///-\n                    /ooo+::://////:---:/+oooo//:\n                   -o+/::///////:-      -:/+o+//-\n                   :-:///////:-            -:/://\n                     -////:-                 --//:\n                       --                       -:\n"
  },
  {
    "path": "index.html",
    "content": "<!doctype html>\n<!--[if lt IE 9]>      <html class=\"no-js oldie no-fontface\" lang=\"en\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html class=\"no-js no-fontface\" lang=\"en\">   <!--<![endif]-->\n<head>\n    <meta charset=\"utf-8\">\n    <title>Move The Web Forward | Guide to getting involved with standards and browser development</title>\n    <meta name=\"description\" content=\"What you can do as a front-end developer\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, minimum-scale=1\">\n\n    <!-- For iPhone 4 with high-resolution Retina display: -->\n    <link rel=\"apple-touch-icon-precomposed\" sizes=\"114x114\" href=\"apple-touch-icon-114x114-precomposed.png\">\n    <!-- For first-generation iPad: -->\n    <link rel=\"apple-touch-icon-precomposed\" sizes=\"72x72\" href=\"apple-touch-icon-72x72-precomposed.png\">\n    <!-- For non-Retina iPhone, iPod Touch, and Android 2.1+ devices: -->\n    <link rel=\"apple-touch-icon-precomposed\" href=\"apple-touch-icon-precomposed.png\">\n\n    <link rel=\"stylesheet\" href=\"css/style.css\">\n\n    <!-- Should be combined: -->\n    <script src=\"js/libs/modernizr.min.js\"></script>\n    <script src=\"js/controller.js\"></script>\n</head>\n\n<body>\n  <b class=\"gimmick\"><i></i><i></i><i></i></b>\n    <header class=\"col-ab\">\n        <div class=\"lead\">\n            <h1 class=\"hed-lead\">Move the Web Forward<span></span></h1>\n            <h2 class=\"subhed-lead\">You can make the web as awesome as you want it to be.</h2>\n            <p class=\"subhed\">You love web standards. You want to give back to the community. Curious about where to start? <b>We're here to help.</b></p>\n        </div>\n        <div class=\"col-split\">\n            <p>Whether you're a talented web developer,  web-slinging since the days of tables and <code>font</code> tags, or you're a hobbyist hacker, there are a number ways for you to give back. Below, we list some of the ways that anyone can contribute back to the web platform.\n            <p>Our goal is to make it easy for anyone to get started contributing to the platform, whether that's learning more about how it works, teaching others, or writing specs. The web has grown due to people like you, and we want to make it even easier for people like you to give back.\n        </div>\n        <p style=\"font-size:90%\">Also available in <a href=\"/ar\">عربى</a>, <a href=\"/cn\">中文</a> and <a href=\"/pt-br\">Brazilian Portuguese</a>.\n    </header>\n\n    <div id=\"nav_container\">\n      <nav id=\"toc\">\n        <ul>\n          <li><a href=#levelup>Level up!</a></li>\n          <li><a href=#digdeep>Dig Deep</a></li>\n          <li><a href=#virtuoso>Virtuoso</a></li>\n        </ul>\n      </nav>\n    </div>\n\n    <article class=\"section\">\n        <div class=\"standout\" id=levelup>\n            <h1 class=\"hed\">Level up!</h1>\n            <h2 class=\"subhed\">You're damn good at what you do. Let's dive into the community!</h2>\n        </div>\n\n        <section id=\"learn\" class=\"col-ab\">\n            <div class=\"col-a\">\n              <h1 class=\"hed\">Learn</h1>\n              <p>One of the most beautiful things about the web is that it's constantly changing. While these changes and improvements can be overwhelming, we're here to help you get caught up! Here are some great resources to walk you through how browsers work, and help keep you up to date on their improvements.</p>\n\n              <h2 id=\"how_do_i_keep_up_with_what8217s_landing_in_browsers\" class=\"subhed\">How do I keep up with what&#8217;s landing in browsers?</h2>\n              <ul>\n                <li><a href=\"http://updates.html5rocks.com/2011/10/Keeping-up-with-HTML5-and-browser-support\">Keeping up with HTML5 and browser support</a> - a list of resources that capture all of these changing things</li>\n                <li><a href=\"https://blog.whatwg.org/\">The WHATWG Blog</a> - summaries of weekly web standards activity</li>\n                <li><a href=\"https://www.w3.org/blog/category/open-web/\">W3C&#8217;s open web</a> - discussions within W3C and the Web community at large</li>\n                <li><a href=\"https://dev.opera.com/blog/\">Dev.Opera Blog</a> - tracks changes to Opera&#8217;s web platform</li>\n                <li><a href=\"https://developers.google.com/web/updates/\">Web Updates in Google Developers</a> - discover the latest API's coming to the Web Platform</li>\n\n                <li><a href=\"https://hacks.mozilla.org/\">Mozilla Hacks</a> - cool apps and HTML5 features</li>\n                <li><a href=\"https://dev.windows.com/en-us/microsoft-edge/\">MSEdge Dev Resources</a> - Developer Resources for Microsoft Edge</li>\n                <li><a href=\"https://blog.chromium.org/\">Chromium Blog</a> - tracks changes to Chromium and Chrome\n                <li><a href=\"http://blog.servo.org/\">Servo Blog</a> - publisher of This Week in Servo</li>\n              </ul>\n\n              <h3 id=\"follow_them_on_twitter\" class=\"subhed\">Follow them on Twitter</h3>\n                <p>\n                    You should probably follow: <a href=\"https://twitter.com/oDevRel\">@oDevRel</a> (Opera developer relations), <a href=\"https://twitter.com/ChromiumDev\">@ChromiumDev</a> (Chrome developer relations), <a href=\"https://twitter.com/mozhacks\">@mozhacks</a> (Mozilla&#8217;s web developer outpost), <a href=\"https://twitter.com/webkit\">@webkit</a> (the WebKit Open Source Project) & <a href=\"https://twitter.com/MSEdgeDev\">@MSEdgeDev</a> (Microsoft Web Platform Team).\n                </p>\n\n              <h2 id=\"how_do_i_understand_how_browsers_work\" class=\"subhed\">How do I understand how browsers work?</h2>\n\n              <ul>\n                <li><a href=\"http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/\">How Browsers Work: Behind the Scenes of Modern Web Browsers</a> - in-depth look at how a browser works</li>\n              </ul>\n\n              <h2 id=\"other_learning_resources\" class=\"subhed\">Other learning resources</h2>\n\n              <ul>\n                <li><a href=\"https://css-tricks.com\">CSS-tricks</a> - provides a wealth of articles, tutorials, and downloads for the web design community.</li>\n                <li><a href=\"http://html5doctor.com\">HTML5doctor</a> - a great resource for people wanting to learn about HTML5, its semantics, and how to implement it today!</li>\n                <li><a href=\"https://www.webplatform.org/\">WebPlatform.org</a> - Community web development documentation wiki.</li>\n                <li><a href=\"http://diveintohtml5.info/\">Dive into HTML5</a> - takes an in depth look at a selection of HTML5 features.</li>\n                <li><a href=\"https://addyosmani.com/blog/\">Addy Osmani&#8217;s blog</a> - tons of great articles for people who want to learn more about jQuery, JavaScript, HTML5, and CSS3.</li>\n                <li><a href=\"http://paulirish.com\">Paul Irish&#8217;s blog</a> - all about helping you build cool websites and keeping you up to date on the latest news.</li>\n                <li><a href=\"https://dev.opera.com\">Dev.Opera</a> - articles for learning about HTML5 features.</li>\n                <li><a href=\"https://blogs.windows.com/msedgedev/\">MS Edge Dev Blog</a> - official blog of the Microsoft Edge Web Platform Team</li>\n                <li><a href=\"http://paulirish.com/2011/web-browser-frontend-and-standards-feeds-to-follow/\">Web browser, frontend and standards feeds to follow</a> </li>\n                <li><a href=\"http://yuilibrary.com/theater/\">YUI Theater</a> - videos of talks about frontend engineering and web technologies given at Yahoo! over the years (many of them unrelated to YUI).</li>\n                <li><a href=\"http://www.adobe.com/devnet/html5.html\">Adobe Developer Connection</a> - articles and videos for learning about HTML5, CSS3 and mobile development.</li>\n              </ul>\n\n              <h2 id=\"reference_docs_wikis\" class=\"subhed\">Reference docs/wikis</h2>\n\n              <ul>\n                <li><a href=\"https://developer.mozilla.org/en-US/\">Mozilla&#8217;s MDN</a> - awesome documentation regarding HTML, CSS, JavaScript, the DOM, and more. It&#8217;s also a great place to contribute! Read <a href=\"https://developer.mozilla.org/docs/MDN/Contribute/Tasks\">their contribution docs</a> and learn how to <a href=\"https://developer.mozilla.org/Project:en/Getting_started\">get started</a>.</li>\n                <li><a href=\"https://developer.mozilla.org/Writing_Forward_Compatible_Websites\">Forward-compatible websites</a> - list of best practices for creating websites that won&#8217;t break when browsers are updated.</li>\n                <li><a href=\"http://html5please.com/\">HTML5 Please - Use new and shiny responsibly</a> - Encyclopedia for HTML5 features across browsers, look up specific features and see when/if you can use it.</li>\n                <li><a href=\"http://caniuse.com/\">Can I Use</a> - Compatibility tables for support of HTML5, CSS3, SVG and more in desktop and mobile browsers.</li>\n              </ul>\n          </div>\n          <div class=\"col-b\">\n            <section class=\"getinvolved\">\n              <h2 class=\"subhed\">Itching to learn?</h2>\n              <div class=\"task\" data-hashtag=\"#learn\">\n                  <p>All it takes is a quick read of a few articles or tweets and you can scratch that knowledge bug! Trust us &ndash; once you&#8217;ve gotten started, it just keeps getting easier.</p>\n                  <a href=\"#\" class=\"pledge\">Yes, I want to do this!</a>\n                  <div class=\"pledges\"><p>Here are some developers who want to do this too:</p></div>\n              </div>\n            </section>\n          </div>\n          </section>\n\n        <section id=\"meetups\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">Meet like-minded folks</h1>\n            <p>Attending local meetups and conferences is a great way to connect with other developers to learn, share resources, and bring new ideas and collaborations to life. Sites like <a href=\"http://meetup.com\">Meetup</a> and <a href=\"http://lanyrd.com\">Lanyrd</a> can help you find events in your neighborhood.</p>\n          </div>\n        </section>\n        <section id=\"askhelp\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">Ask for help</h1>\n            <h2 id=\"answer_questions_and_participate_in_conversations_on_irc\" class=\"subhed\">Answer questions and participate in conversations on IRC</h2>\n            <p><a href=\"http://richard.esplins.org/siwi/2011/07/08/getting-started-freenode-irc/\">How to get started with freenode and irc</a></p>\n            <ul>\n              <li><b>Freenode IRC channels:</b> #html5 / #css / #javascript / #whatwg / #jquery / #yui / #dojo / #web / #chromium / #webkit / <span title=\"browser based game development\">#bbg</span> (on <a href=\"https://webchat.freenode.net\">irc.freenode.net</a>) </li>\n              <li id=\"mozilla_irc\"><b>Mozilla IRC channel:</b> #js (on <a href=\"http://irc.mozilla.org\">irc.mozilla.org</a>)</li>\n            </ul>\n\n            <h2 id=\"how_to_ask_for_help\" class=\"subhed\">How to ask for help</h2>\n            <ol class=\"tasks\">\n              <li>You&#8217;ll probably want to <a href=\"https://css-tricks.com/seriously-just-make-a-jsfiddle/\">make a jsfiddle first</a>.</li>\n              <li><a href=\"https://css-tricks.com/reduced-test-cases/\">Create a reduced test case</a>.</li>\n              <li>Remember: be specific!</li>\n              <li>Ask on IRC, <a href=\"http://stackoverflow.com\">StackOverflow</a> (even its <a href=\"http://chat.stackoverflow.com/rooms/17/javascript\">javascript chatroom</a>), or a group of friends.\n            </ol>\n          </div>\n\n          <div class=\"col-b\">\n          <section class=\"getinvolved\">\n              <h2 class=\"subhed\">A helping hand.</h2>\n              <div class=\"task\" data-hashtag=\"#ask4help\">\n                <p>We've all gotten to where we are by relying on others for help at some time or another. Don't be shy, and just ask! Just please make a jsfiddle first. =D</p>\n                <a href=\"#\" class=\"pledge\">Yes, I want to do this!</a>\n                <div class=\"pledges\"><p>Here are some developers who want to do this too:</p></div>\n              </div>\n             </section>\n          </div>\n        </section>\n    </article>\n\n    <article class=\"section\">\n        <div class=\"standout\" id=digdeep>\n            <h1 class=\"hed\">Dig Deep</h1>\n            <h2 class=\"subhed\">You clearly know your way around. Now it's time to show it.</h2>\n        </div>\n        <section id=\"helpothers\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">Help others</h1>\n            <p>We've all got to start somewhere! Helping others reassures your knowledge, and also broadens the amount of concepts you're exposed to. Below are some great open-source projects that are always looking for help. Remember - no patch is too small!</p>\n            <h2 id=\"open_source_projects_worth_your_time\" class=\"subhed\">Open-Source projects worth your time</h2>\n\n            <ul>\n              <li><a href=\"https://github.com/h5bp/html5-boilerplate\">HTML5 Boilerplate</a> <span>- a clearinghouse for frontend dev best practices</span>\n              <li><a href=\"https://github.com/jquery/learn.jquery.com\">jQuery Learning Site</a> <span>- educational site for the popular jQuery library</span>\n              <li><a href=\"https://github.com/jquery/jquery-mobile\">jQuery Mobile</a> <span>- mobile progressive enhancement best practices</span>\n              <li><a href=\"https://github.com/Modernizr/Modernizr\">Modernizr</a> <span>- feature detection's finest</span>\n              <li><a href=\"https://github.com/twbs/bootstrap\">Bootstrap</a> <span>- a css and js toolkit designed to kickstart development of webapps</span>\n              <li><a href=\"https://necolas.github.io/normalize.css/\">Normalize.css</a> <span>- make all browsers render markup the same</span>\n              <li><a href=\"http://dojotoolkit.org/get-involved\">Dojo</a> <span>- the comprehensive frontend app development toolkit</span>\n              <li><a href=\"https://github.com/h5bp/lazyweb-requests/issues?state=open\">Lazyweb requests</a> <span>- Web tools and solutions that would be cool to have for web developers.</span>\n            </ul>\n            <p>Do what is asked in <a href=\"#how_to_ask_for_help\">&#8216;ask for help&#8217;</a> above and check out <a href=\"http://addyosmani.com/blog/getting-involved-with-open-source/\">Addy Osmani&#8217;s podcast about getting involved</a>!</p>\n\n            <h2 id=\"help_write_documentation\" class=\"subhed\">Write documentation</h2>\n            <ul>\n              <li><a href=\"http://www.webplatform.org/\">Web Platform</a> <span>- a community-driven source for comprehensive web developer documentation</span></li>\n            </ul>\n\n          </div>\n\n          <div class=\"col-b\">\n            <section class=\"getinvolved\">\n              <h2 class=\"subhed\">Pass it on!</h2>\n              <div class=\"task\" data-hashtag=\"#helpothers\">\n                <p>Reading awesome code leads to writing awesome code. Look into the great projects listed below, and help them grow to be even more great than they already are.</p>\n                <a href=\"#\" class=\"pledge\">Yes, I want to do this!</a>\n                <div class=\"pledges\"><p>Here are some developers who want to do this too:</p></div>\n              </div>\n            </section>\n          </div>\n        </section>\n\n        <section id=\"specs\" class=\"col-ab\">\n            <div class=\"col-a\">\n                <h1 class=\"hed\">Give feedback on specifications</h1>\n\n                <p>Specs codify the expected behavior. They are developed by Working Groups (WG) along with active discussion on mailing lists. While we can’t always be certain that all browser vendors will adhere to the rules set forth in a spec, they provide us with something that we, as developers, can standardize against.</p>\n\n                <ul>\n                    <li>Learn the <a href=\"http://diveintohtml5.info/past.html\">history of HTML</a>.</li>\n                    <li>Take an <a href=\"http://fantasai.inkedblade.net/weblog/2011/inside-csswg/\">inside look at how the CSS WG works</a>.</li>\n                    <li>Subscribe to these mailing lists to follow and contribute to the discussions that drive the web:\n                        <ul class=\"resources\">\n                            <li><a href=\"http://lists.w3.org/Archives/Public/public-webapps/\">public-webapps</a> -  technical discussion for the Web Applications Working Group</li>\n                            <li><a href=\"http://lists.w3.org/Archives/Public/www-style/\">www-style</a> - technical discussion on Cascading Style Sheets (CSS) and its specifications</li>\n                            <li><a href=\"http://lists.whatwg.org/pipermail/whatwg-whatwg.org/\">whatwg</a> - WHATWG's mailing list</li>\n                            <li><a href=\"http://lists.w3.org/Archives/Public/public-html/\">public-html</a> - W3C HTML Working Group</li>\n                            <li><a href=\"http://lists.w3.org/Archives/Public/www-dom/\">www-dom</a> - where the DOM is improved</li>\n                            <li><a href=\"http://lists.w3.org/Archives/Public/public-fx/\">public-fx</a> - issues affecting the CSS and SVG Working Groups</li>\n                        </ul>\n                    </li>\n                    <li>Read through the <a href=\"http://developers.whatwg.org/\">HTML LS Spec for developers</a> (the implementor stuff removed, formatted beautifully for you).</li>\n                    <li>The easiest way to comment or give feedback on the contents of the <a href=\"http://www.whatwg.org/specs/web-apps/current-work/multipage/\">HTML specification</a> is to select the text you want to comment on and leave a message using the form at the bottom of the page.</li>\n                    <li>\n                        See the latest commits to the HTML and CSS specs by following their respective working groups on Twitter:\n                        <ul class=\"resources\">\n                            <li><a href=\"https://twitter.com/whatwg\">@whatwg</a></li>\n                            <li><a href=\"https://twitter.com/csscommits\">@csscommits</a></li>\n                        </ul>\n                    </li>\n                </ul>\n            </div>\n            <div class=\"col-b\">\n              <section class=\"getinvolved\">\n                <h2 class=\"subhed\">Are you specced out?</h2>\n                <div class=\"task\" data-hashtag=\"#feedback\">\n                  <p>We're the ones using the specs, so why don't we help make specs we love? Let's stand up for standards, and help make these even better!</p>\n                  <a href=\"#\" class=\"pledge\">Yes, I want to do this!</a>\n                  <div class=\"pledges\"><p>Here are some developers who want to do this too:</p></div>\n                </div>\n              </section>\n            </div>\n        </section>\n\n        <section id=\"explore\" class=\"col-ab\">\n            <div class=\"col-a\">\n              <h1 class=\"hed\">Explore frontend features</h1>\n              <p>Once you&#8217;ve picked up the basics, it&#8217;s time to dive a bit deeper into the current (and future) state of web standards! Get excited, because here, we check out advanced CSS, brand-new HTML5 features/APIs, and even what the future of these languages are expected to be. Several new capabilities are now available in browsers, and exploring these new capabilities will help us push the web forward!</p>\n\n            <h2 id=\"examples_of_how_to_explore_features_well\" class=\"subhed\">Examples of how to explore features well</h2>\n            <ul>\n              <li><a href=\"http://perfectionkills.com/global-eval-what-are-the-options/\">Global <code>eval</code>: what are the options?</a> <span> - kangax</span>\n              <li><a href=\"http://www.webdirections.org/blog/let-the-web-move-you-css3-animations-and-transitions/\">Let the Web move you — CSS3 Animations and Transitions</a> <span> - John Allsopp</span>\n              <li><a href=\"http://addyosmani.com/largescalejavascript/\">Patterns For Large-Scale JavaScript Application Architecture</a> <span> - Addy Osmani</span>\n              <li><a href=\"http://designfestival.com/the-cicada-principle-and-why-it-matters-to-web-designers/\">The Cicada Principle and why it matters to web designers</a> <span> - Alex Walker</span>\n              <li><a href=\"http://css-tricks.com/snippets/css/keyframe-animation-syntax/\">Keyframe animation syntax</a> <span> - Chris Coyier</span>\n              <li><a href=\"http://www.blog.highub.com/css/whats-new-in-css-selectors-level-4/\">What's new in CSS Selectors (Level 4)</a> <span> - Shi Chuan</span>\n              <li><a href=\"http://mathiasbynens.be/notes/touch-icons\">Everything you always wanted to know about touch icons</a> <span> - Mathias Bynens</span>\n              <li><a href=\"http://coding.smashingmagazine.com/2009/09/15/the-z-index-css-property-a-comprehensive-look/\">The z-index CSS Property: A Comprehensive Look</a> <span> - Louis Lazaris</span>\n            </ul>\n\n            <h2 id=\"cool_ideas_to_explore_more\" class=\"subhed\">Cool features to explore more (and write about)</h2>\n\n            <p>Browsers ship new CSS features all the time. The vendor prefixes we love to hate are actually there so we developers can provide feedback on whether the feature meets our needs. Encourage yourself to investigate if they do! This <a href=\"http://peter.sh/experiments/vendor-prefixed-css-property-overview/\">vendor-prefixed CSS property overview</a>, by Peter Beverloo, has a lot of experimental CSS mentioned; much of which is not well understood. Consider writing about them and the items below:\n\n              <ul>\n                <li><a href=\"https://developer.mozilla.org/En/CSS/%3Achecked\">The :checked selector</a> / <a href=\"http://dev.w3.org/csswg/css3-images/#object-fit\">object-fit</a>  / <a href=\"https://developer.mozilla.org/en/CSS/background-clip\">background-clip</a> / <a href=\"http://dropshado.ws/post/1015351370/webkit-line-clamp\">-webkit-line-clamp</a> / <a href=\"https://developer.mozilla.org/en/CSS/text-overflow\">text-overflow</a> / <a href=\"https://developer.mozilla.org/En/CSS/Box-sizing\">box-sizing</a> / <a href=\"https://developer.mozilla.org/en/CSS3_Columns\">CSS columns</a></li>\n                <li><code>history.pushState()</code>, HTML5 input <code>checkValidity()</code>, <code>getClientRects</code> / <code>getBoundingClientRect</code>, WebKit's <a href=\"http://developer.apple.com/library/safari/#documentation/DataManagement/Reference/DOMWindowAdditionsReference/DOMWindowAdditions/DOMWindowAdditions.html\">ConvertPointFromPageToNode</a>\n                <li><a href=\"http://www.w3.org/TR/css3-gcpm/\">CSS Generated Content for Paged Media Module (GCPM)</a>\n                <li>Differences between <code>word-wrap</code>, <code>word-break</code>, and <code>white-space</code>\n                <li>Harmony features like <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:let\">let</a> / <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:block_scoped_bindings\">block-scoped bindings</a> / block functions /  <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:destructuring\">destructuring</a> / <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:rest_parameters\">rest parameters</a> / <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:parameter_default_values\">default param values</a>.\n                <li><a href=\"http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html\">Web Components Explained (very early draft)</a>\n\n                <li><strong>Any features from these presentations:</strong>\n                  <ul>\n                    <li><a href=\"http://vimeo.com/32135328\">The Future of CSS</a> <span>- Tab Atkins on what to expect from CSS in the future.</span>\n                    <li><a href=\"http://infrequently.org/11/fronteers/fronteers.html\">Data, Semantics, and the Process of Progress </a> <span>- browser evolution, Component Model, MDV</span>\n                    <li><a href=\"http://infrequently.org/11/ldnjs/ldnjs.html\">[JS|DOM].next()</a> <span>- Alex Russell on the next version of ECMAScript.</span>\n                    <li><a href=\"http://lea.verou.me/css3-secrets/\">CSS3 Secrets</a> <span>- an interactive presentation on advanced CSS3 functionality.</span>\n                    <li><a href=\"http://nimbu.in/w3conf/\">The Future of Layouts in CSS</a> <span>- and how emerging specs will add proper layout control to CSS</span>\n                    <li><a href=\"http://mezzoblue.com/presentations/2011/fowd/FOWD.pdf\">The Future of CSS</a> <span>- an overview of a number of surfacing CSS features.</span>\n\n                </ul>\n              </ul>\n\n            </div>\n            <div class=\"col-b\">\n            <section class=\"getinvolved\">\n                <h2 class=\"subhed\">Explore the unknown!</h2>\n                <div class=\"task\" data-hashtag=\"#explore\">\n                  <p>Go for it! The only way to move the web forward is to dig in and used advanced features and APIs. Have fun - we know you will!</p>\n                  <a href=\"#\" class=\"pledge\">Yes, I want to do this!</a>\n                  <div class=\"pledges\"><p>Here are some developers who want to do this too:</p></div>\n                </div>\n             </section>\n          </div>\n        </section>\n\n\n        <section id=\"write\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">Write</h1>\n            <p>Publish what you learn and don&#8217;t be afraid to make mistakes. Publish to your personal blog and keep your posts updated. Be sure to speak with your own voice! Remember that it is okay to not be an absolute authority on a subject to author a post! Always ask questions and prompt conversations. There is seldom a wrong question or a wrong answer.</p>\n\n            <p>Teaching is a great learning tool as well. So, even if you are getting started in an area, you’re helping yourself by writing about it as well. You can always consider asking a mentor or friend for a technical review. (Addy&#8217;s done that with aplomb.)</p>\n\n            <h2 id=\"what_should_you_start_to_learn_about\" class=\"subhed\">What should you write about?</h2>\n\n            <p>Something you can teach others! Here are some ideas:</p>\n\n            <ul>\n                <li>Why do the <code>&lt;br&gt;</code> and <code>&lt;hr&gt;</code> elements (or any element) exist?</li>\n                <li>How to create a slideshow with the least amount of code?</li>\n                <li>What is the DOM? Why does it exist?</li>\n                <li>Check how browsers implement a specific property and compare it to the spec.</li>\n                <li>How a popular website implements its homepage (with suggestions for improvement).</li>\n                <li>How you would fix a popular website's faults (long load-time, invalid JS, etc.).</li>\n                <li>Take a popular demo and make it something else (or use it practically).</li>\n                <li>Make a summary of popular ideas around the web lately.</li>\n                <li>Your experience contributing to an open-source project.</li>\n                <li>How CSS preprocessors can lead to stringy and bad code if not managed correctly.</li>\n                <li>If you are a native speaker of a language other than English:\n                <ul class=\"resources\">\n                  <li>Translate some popular English web dev posts.</li>\n                  <li>Elaborate on some of the features in the specs.</li>\n                </ul>\n              </li>\n            </ul>\n          </div>\n          <div class=\"col-b\">\n            <section class=\"getinvolved\">\n              <h2 class=\"subhed\">Write this down!</h2>\n              <div class=\"task\" data-hashtag=\"#write\">\n                <p>Regardless of how many twitter followers or github watchers you have - write about what you learn!</p>\n                <a href=\"#\" class=\"pledge\">Yes, I want to do this!</a>\n                <div class=\"pledges\"><p>Here are some developers who want to do this too:</p></div>\n              </div>\n            </section>\n          </div>\n        </section>\n        <section id=\"filebugs\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">File bugs</h1>\n            <p>Seriously, all browser vendors would much rather you file tickets with them than tweet about bugs. =D</p>\n            <ul>\n              <li><a href=\"http://coding.smashingmagazine.com/2011/09/07/help-the-community-report-browser-bugs/\">Help the Community: Report Browser Bugs</a> by Lea Verou</li>\n              <li><a href=\"http://ejohn.org/blog/a-web-developers-responsibility/\">A Web Developer&#8217;s Responsibility</a> by John Resig</li>\n              <li><a href=\"http://a11ybugs.org/\">Help prioritize browser accessibility bugs</a> by Vlad Alexander</li>\n              <li>\n                <p>Browser issue trackers - search for existing bug reports or submit new ones:</p>\n                <ul class=\"resources\">\n                  <li><a href=\"https://bugzilla.mozilla.org/\">Mozilla's bugzilla</a></li>\n                  <li><a href=\"https://bugs.webkit.org/\">WebKit bugs</a></li>\n                  <li><a href=\"http://crbug.com/\">Chrome bugs</a></li>\n                  <li><a href=\"http://www.opera.com/support/bugs/\">Opera bugs</a></li>\n                  <li><a href=\"https://connect.microsoft.com/site/sitehome.aspx?SiteID=136\">Help IE</a></li>\n                </ul>\n              </li>\n            </ul>\n          </div>\n          <div class=\"col-b\">\n            <section class=\"getinvolved\">\n              <h2 class=\"subhed\">Stop bugging out!</h2>\n              <div class=\"task\" data-hashtag=\"#filebugs\">\n                <p>This is the quickest way for browsers to get better - by filing and working on bugs. It takes just a few moments, and anybody can do it.</p>\n                <a href=\"#\" class=\"pledge\">Yes, I want to do this!</a>\n                <div class=\"pledges\"><p>Here are some developers who want to do this too:</p></div>\n              </div>\n            </section>\n          </div>\n        </section>\n    </article>\n    <article class=\"section\">\n      <div class=\"standout\" id=virtuoso>\n        <h1 class=\"hed\">Virtuoso!</h1>\n        <h2 class=\"subhed\">You've come a long way; you clearly know your stuff! May we suggest you these?</h2>\n      </div>\n      <section id=\"hack\" class=\"col-ab\">\n        <div class=\"col-a\">\n          <h1 class=\"hed\">Hack!</h1>\n          <p>Push the web to its limits! Hack on CSS, advanced HTML, and JavaScript. Hack on the browser's rendering engine. Fork github repos, dig through the code, and keep on learning. Let's make the web more awesome. There are so many ways:</p>\n          <h2 id=\"contribute_to_browsers\" class=\"subhed\">Contribute to browsers</h2>\n          <ul>\n            <li>Help build devtools, like the <a href=\"http://trac.webkit.org/wiki/WebInspector\">WebKit Inspector</a>.\n            They are written in HTML, CSS, and JS so you don&#8217;t need to be a C++ programmer to contribute to these.\n            Write patches!</li>\n            <li><a href=\"https://developer.mozilla.org/en/Gecko_BugAThon\">Reduce test cases for Mozilla</a></li>\n            <li>Hack on Gecko\n              <ul>\n                <li>Read the developer guide for <a href=\"https://developer.mozilla.org/En/Developer_Guide\">getting started with Gecko development</a>.\n                <li>A <a href=\"https://bugzilla.mozilla.org/buglist.cgi?quicksearch=%22[mentor%3D%22&list_id=1800469\">list of &#8220;good first bugs&#8221; for Firefox/Gecko</a>\n                <li>Join #introduction and #developers on <a href=\"#mozilla_irc\">Mozilla's IRC server</a>\n              </ul>\n            <li>Hack on Blink\n              <ul>\n                <li><a href=\"http://dev.chromium.org/developers/contributing-code\">Google&#8217;s guide on how to contribute to Blink</a>\n              </ul>\n            <li>Hack on WebKit\n              <ul>\n                <li>Read the guide for <a href=\"https://www.webkit.org/coding/contributing.html\">contributing code to WebKit</a>.\n            </ul>\n          </ul>\n\n          <h2 id=\"contribute_to_testsuites\" class=\"subhed\">Contribute to Test Suites</h2>\n\n          <p>Test cases are fundamental to standards and to browsers. They assure things work the same across browsers. Yet right now, the W3C test suites don't have nearly as many tests as they need. Tests are written in the languages of web developers: HTML, CSS, and JavaScript. </p>\n\n          <ul>\n            <li>Get information on the\n              <a href=\"https://github.com/w3c/web-platform-tests\">W3C Web Platform Tests Project</a>\n              and the <a href=\"https://github.com/w3c/csswg-test\">W3C CSS Test Suite</a>.\n            </li>\n            <li>Look into <a href=\"http://www.w3.org/html/wg/wiki/Testing#New_tests\">upstreaming some existing tests</a> into the W3C Test suite.</li>\n            <li>Upstream <a href=\"http://trac.webkit.org/browser/trunk/LayoutTests\">WebKit&#8217;s LayoutTests</a>. <span>Also see the LayoutTests <a href=\"http://www.webkit.org/blog/1452/layout-tests-theory/\">theory</a> & <a href=\"http://www.webkit.org/blog/1456/layout-tests-practice/\">practice</a>.</span></li>\n            <li>Upstream <a href=\"https://developer.mozilla.org/en/Mochitest\">Mozilla&#8217;s Mochitests</a>.</li>\n            <li>Join the conversation on <a href=\"http://lists.w3.org/Archives/Public/public-webapps-testsuite/\">public-webapps-testsuite</a>, <a href=\"http://lists.w3.org/Archives/Public/public-html-testsuite/\">public-html-testsuite</a>, and <a href=\"http://lists.w3.org/Archives/Public/public-css-testsuite/\">public-css-testsuite</a>.</li>\n            <li>Contribute to HTML5 Audio on <a href=\"http://areweplayingyet.org\">the AreWePlayingYet? test suite</a>.</li>\n          </ul>\n\n\n          <h2 id=\"contribute_to_specs\" class=\"subhed\">Contribute to specifications</h2>\n          <ul>\n            <li>Review existing bugs on <a href=\"http://www.w3.org/Bugs/Public/\">W3C bugzilla</a> <span>- and learn <a href=\"http://wiki.whatwg.org/wiki/Bugzilla_conventions\">Bugzilla conventions</a>.</span>\n            <li>Particpate in <a href=\"http://www.whatwg.org/mailing-list\">WHATWG</a> / <a href=\"http://lists.w3.org/Archives/Public/public-webapps/\">public-webapps</a> / <a href=\"http://lists.w3.org/Archives/Public/www-style/\">www-style</a> / <a href=\"http://lists.w3.org/Archives/Public/public-fx/\">public-fx</a> discussions.</li>\n            <li><a href=\"http://dev.chromium.org/developers/how-tos/make-a-web-standards-proposal\">Make a web standards proposal</a>. <span>(this guide tells you how!)</span>\n            <li><a href=\"http://wiki.whatwg.org/wiki/How_to_write_a_spec\">Write specs!</a> <span>we could certainly use more spec writers.</span></li>\n          </ul>\n          <h2 id=\"contribute_to_validators\" class=\"subhed\">Contribute to validators</h2>\n          <ul>\n            <li>\n              <a href=\"https://github.com/validator/validator\">HTML Validator</a> <span>would appreciate contributions.</span>\n            <li>\n              <a href=\"https://github.com/w3c/css-validator\">CSS Validator</a> <span>can always use some help.</span>\n            <li>\n              <a href=\"https://github.com/annevk/webvtt\">WebVTT</a> <span>a video subtitling format, is an active area of standards interest</span>\n            </ul>\n\n        <h2 id=\"contribute_to_projects\" class=\"subhed\">Contribute to projects</h2>\n        <ul>\n          <li>\n          <a href=\"https://github.com/h5bp/lazyweb-requests/issues/\">Lazyweb Requests</a> <span>are some ideas for awesome projects the web would love to see built.</span>\n          </li>\n        </ul>\n        </div>\n        <div class=\"col-b\">\n          <section class=\"getinvolved\">\n            <h2 class=\"subhed\">I&#8217;m in your codez!</h2>\n            <div class=\"task\" data-hashtag=\"#hack\">\n              <p>Just build stuff. Experiment, fork repos, dig through code. Contribute to the browsers, specs, validators, or great <a href=\"#open_source_projects_worth_your_time\">open-source projects</a>!</p>\n              <a href=\"#\" class=\"pledge\">Yes, I want to do this!</a>\n              <div class=\"pledges\"><p>Here are some developers who want to do this too:</p></div>\n            </div>\n          </section>\n        </div>\n      </section>\n    </article>\n\n\n\n    <footer class=\"doc\">\n\n      <p class=\"subhed summary\">\n        You can make the web as awesome as you want it to be. Browser vendors, standards editors and library creators actively seek your voice and your contribution. <br>Together we can move the web forward.\n\n      </p>\n\n      <img src=\"img/pugerton.png\" alt=\"Pugerton\">\n\n      <p class=\"subhed\">Made with love &amp; tears by</p>\n\n      <ul class=\"builders\">\n          <li><a href=\"https://twitter.com/wilto\"><img src=\"https://pbs.twimg.com/profile_images/477441227986444289/KHCUqTis_normal.png\" alt=\"Mat Marquis\"> <b>Mat</b> Marquis</a>\n          <li><a href=\"https://twitter.com/aaronforsander\"><img src=\"https://pbs.twimg.com/profile_images/461528075788763138/c7ONSIRm_normal.jpeg\" alt=\"Aaron Forsander\"> <b>Aaron</b> Forsander</a>\n          <li><a href=\"https://twitter.com/connor\"><img src=\"https://pbs.twimg.com/profile_images/526185574039031808/IpDbRAX5_normal.jpeg\" alt=\"Connor Montgomery\"> <b>Connor Montgomery</b></a>\n          <li><a href=\"https://twitter.com/paul_irish\"><img src=\"https://pbs.twimg.com/profile_images/420826194083213312/CP1RmLa3_normal.jpeg\" alt=\"Paul Irish\"> <b>Paul</b> Irish</a>\n          <li><a href=\"https://twitter.com/divya\"><img src=\"https://pbs.twimg.com/profile_images/550530231853776897/kni4F8oM_normal.png\" alt=\"Diviya Manian\"> <b>Divya</b> Manian</a>\n          <li><a href=\"https://twitter.com/necolas\"><img src=\"https://pbs.twimg.com/profile_images/529444560179449857/eKdCJhvp_normal.jpeg\" alt=\"Nicolas Gallagher\"> <b>Nicolas</b> Gallagher</a>\n          <li><a href=\"https://twitter.com/addyosmani\"><img src=\"https://pbs.twimg.com/profile_images/422476220442234880/jlx9HMtr_normal.jpeg\" alt=\"Addy Osmani\"> <b>Addy</b> Osmani</a>\n      </ul>\n\n      <p class=\"others\">&amp; <a href=\"https://github.com/h5bp/movethewebforward/contributors\"><span>all these awesome people</span>.</a></p>\n      <p>Dinos by <a href=\"http://dribbble.com/deathbearbrown\">Sue Lockwood</a> • <a href=\"https://github.com/h5bp/movethewebforward\">Contribute to this project!</a></p>\n    </footer>\n    <script>\n        window._gaq=[['_setAccount','UA-17904194-2'],['_trackPageview']];\n        (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];\n        g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';\n        s.parentNode.insertBefore(g,s)}(document,'script'));\n    </script>\n</body>\n</html>\n"
  },
  {
    "path": "js/controller.js",
    "content": "(function(win, undefined){\n\t\n\tvar doc \t\t = win.document,\n\t\tdocElem \t = doc.documentElement,\n\t\thead\t\t = doc.getElementsByTagName( \"head\" )[0] || docElem,\n\t\tModernizr\t = win.Modernizr;\n\t\t\t\n\t// Supportin’ stuff.\n\tmd = {\n\t\tmobileBreakpoint : window.screen.width >= 480,\n\t\tdevMode : {\n\t\t\tmobileAssets : !!~location.search.indexOf(\"mobile\"),\n\t\t\tbasicAssets\t : !!~location.search.indexOf(\"basic\")\n\t\t},\n\t\tenhanced\t\t : Modernizr.mq || /oldie/.test(document.documentElement.className)\n\t};\n\n\t// If we’re emulating non-MQ browsers for development purposes:\n\tif( md.devMode.basicAssets ) {\n\t\thead.removeChild( doc.getElementById( \"enhanced-css\" ) );\n\t\thead.removeChild( doc.getElementById( \"reset-css\" ) );\n\t\treturn;\n\t}\n\n\t// Non-MQ browser, or in “mobile” preview mode? Exit here:\n\tif( !md.enhanced || md.devMode.mobileAssets ) { \n\t\treturn;\n\t}\n\n\t// If we’ve made it this far, we’re enhanced. Add a class to style against.\n\tdocElem.className += \" enhanced\";\n\n\t// Add a class for “homescreen mode”:\n\tif ( win.navigator.standalone ) {\n\t\tdocElem.className += \" standalone\";\t\n\t}\n\n\t// Callback for body-dependent scripts:\n\tmd.bodyready = (function(){\n\n\t\tvar callbackStack \t= [],\n\t\t\tcheckRun\t\t= function( callback ){\n\n\t\t\t\tif( callback ){\n\t\t\t\t\tcallbackStack.push( callback );\n\t\t\t\t}\n\n\t\t\t\tif( doc.body ){\n\t\t\t\t\twhile( callbackStack[0] && typeof( callbackStack[0] ) === \"function\" ){\n\t\t\t\t\t\tcallbackStack.shift().call( win );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse{\n\t\t\t\t\tsetTimeout(checkRun, 15); \n\t\t\t\t}\n\t\t\t};\n\t\t\treturn checkRun;\n\t})();\n\n\t// Loading functions available on md.load:\n\tmd.load = {};\n\n\t// Define md.load.style:\n\tmd.load.style = function( href, media ){\n\n\t\tif( !href ){ return; }\n\n\t\tvar lk\t\t\t= doc.createElement( \"link\" ),\n\t\t\tlinks\t\t= head.getElementsByTagName(\"link\"),\n\t\t\tlastlink\t= links[links.length-1];\n\t\t\tlk.type \t= \"text/css\";\n\t\t\tlk.href \t= href;\n\t\t\tlk.rel\t\t= \"stylesheet\";\n\t\t\tif( media ){\n\t\t\t\tlk.media = media;\n\t\t\t}\n\n\t\t\t//if respond.js is present, be sure to update its media queries cache once this stylesheet loads\n\t\t\t//IE should have no problems with the load event on links, unlike other browsers\n\t\t\tif( \"respond\" in window ){\n\t\t\t\tlk.onload = respond.update;\n\t\t\t}\n\n\t\t\thead.insertBefore(lk, lastlink.nextSibling );\n\t\t\t\n\t};\n\n\t// Non-MQ browser, or in one of the two development modes? Exit here:\n\tif( !md.enhanced || md.devMode.mobileAssets || md.devMode.basicAssets ) { \n\t\treturn;\n\t}\n\tModernizr.load([\n    {\n      test: md.enhanced,\n      yep: [\n        '/js/libs/storage.js',\n        '/js/libs/jquery.min.js',\n        '/js/plugins.js',\n        '/js/init.js'\n      ]\n    },\n    { \n        test: md.mobileBreakpoint,\n        yep: '/js/libs/fittext.js'\n    }\n    ]);\n\t\t\n\t// Wait for body to be ready for the rest, so we can check the body class and load accordingly:\n\tmd.bodyready(function(){\n\n\t\t// Load custom fonts above:\n\t\tif( md.mobileBreakpoint && !md.devMode.mobileAssets ){\t\n                        md.load.style( '/css/fonts.css' );\n\t\t\t// Remove no-fontface class, for fallback font styling:\n\t\t\tdocElem.className = docElem.className.replace(/\\bno-fontface\\b/,'');\n\t\t}\n\n\t});\n\t\n\t// WebReflection Solution for ensuring domready fires when dynamically appending jQuery in older browsers\n\t(function(h,a,c,k){if(h[a]==null&&h[c]){h[a]=\"loading\";h[c](k,c=function(){h[a]=\"complete\";h.removeEventListener(k,c,!1)},!1)}})(document,\"readyState\",\"addEventListener\",\"DOMContentLoaded\");\n\n})(this);\n"
  },
  {
    "path": "js/init.js",
    "content": "(function( $ ){\n\n  //$.getJSON('/avatars.json')\n  //  .success(function(avatars) {\n  //    $.each(avatars, function(hashtag) {\n  //      var avatarsElem = $(\".task[data-hashtag=\" + hashtag + \"] .pledges\");\n  //      for (var user in this) {\n  //        var image = $('<img>', { src: this[user], title: user });\n  //        var link = $('<a/>', { href: 'http://twitter.com/' + user });\n  //        avatarsElem.append(link.append(image));\n  //      }\n  //    });\n  //  });\n\n  Modernizr.load([{\n      test: window.JSON,\n      nope: '/js/libs/json2.min.js',\n      complete: function() {\n      \t$(\".task\")\n      \t\t.hashTask({\n      \t\t\tmessage         : \"http://movethewebforward.org\",\n      \t\t\teditTweetText   : \"(edit this tweet as you wish. ♡)\",\n      \t\t\tlinkSelector    : function() { return this.find('.pledge') },\n      \t\t\thashtag         : function() { return this.data('hashtag') || '#movethewebforward' },\n      \t\t});\n\n        if (window.__twitterIntentHandler) return;\n        var intentRegex = /twitter\\.com(\\:\\d{2,4})?\\/intent\\/(\\w+)/,\n            windowOptions = 'scrollbars=yes,resizable=yes,toolbar=no,location=yes',\n            width = 550,\n            height = 420,\n            winHeight = screen.height,\n            winWidth = screen.width;\n\n        function handleIntent(e) {\n          e = e || window.event;\n          var target = e.target || e.srcElement,\n              m, left, top;\n\n          while (target && target.nodeName.toLowerCase() !== 'a') {\n            target = target.parentNode;\n          }\n\n          if (target && target.nodeName.toLowerCase() === 'a' && target.href) {\n            m = target.href.match(intentRegex);\n            if (m) {\n              left = Math.round((winWidth / 2) - (width / 2));\n              top = 0;\n\n              if (winHeight > height) {\n                top = Math.round((winHeight / 2) - (height / 2));\n              }\n\n              window.open(target.href, 'intent', windowOptions + ',width=' + width +\n                                                 ',height=' + height + ',left=' + left + ',top=' + top);\n              e.returnValue = false;\n              e.preventDefault && e.preventDefault();\n            }\n          }\n        }\n\n        if (document.addEventListener) {\n          document.addEventListener('click', handleIntent, false);\n        } else if (document.attachEvent) {\n          document.attachEvent('onclick', handleIntent);\n        }\n        window.__twitterIntentHandler = true;\n      }\n  }]);\n\n  (new Image()).src = '/css/img/beanie-webasaurs.gif'\n\n\t\tvar $toc = $('#toc'),\n\t\t  $inlinelinks = $('body div.col-a'),\n\t\t\t$tocLinks = $toc.find('a[href^=\"#\"]'),\n\t\t\t$bodyinlinelinks = $inlinelinks.find('a[href^=\"#\"]'),\n\t\t\tcache = {}, cacheinline = {};\n\t\t\t$docEl = $( document.documentElement ),\n\t\t\t$body = $( document.body ),\n\t\t\t$window = $( window ),\n\t\t\t$scrollable = $body, // default scrollable thingy, which'll be body or docEl (html)\n\t\t\t$parallax1 = $('.gimmick i:first-child'),\n\t\t\t$parallax2 = $('.gimmick i:nth-child(2)'),\n\t\t\t$parallax3 = $('.gimmick i:last-child'),\n\t\t\t$bodyheight = $body.height(),\n      $bodywidth = $body.width(),\n      $headerwidth = $('.lead').width(),\n      $nav = $('#toc'),\n      $originalnavtop = $nav.position().top;\n\t\t\t$navheight = $nav.outerHeight(true);\n\t\t\t$('#nav_container').height($navheight);\n\n\t\t// find out what the hell to scroll ( html or body )\n\t\t// its like we can already tell - spooky\n\t\tif ( $docEl.scrollTop() ) {\n\t\t\t$scrollable = $docEl;\n\t\t} else {\n\t\t\tvar bodyST = $body.scrollTop();\n\t\t\t// if scrolling the body doesn't do anything\n\t\t\tif ( $body.scrollTop( bodyST + 1 ).scrollTop() == bodyST) {\n\t\t\t\t$scrollable = $docEl;\n\t\t\t} else {\n\t\t\t\t// we actually scrolled, so, er, undo it\n\t\t\t\t$body.scrollTop( bodyST - 1 );\n\t\t\t}\n\t\t}\n\n\t\t// build cache\n\t\t$tocLinks.each(function(i,v) {\n\t\t\tvar href =  $( this ).attr( 'href' ),\n\t\t\t\t$target = $( href );\n\t\t\tif ( $target.length ) {\n\t\t\t\tcache[ this.href ] = { link: $(v), target: $target };\n\t\t\t}\n\t\t});\n\n\t\t//build inline cache\n\t\t$bodyinlinelinks.each(function(i,v) {\n\t\t\tvar href =  $( this ).attr( 'href' ),\n\t\t\t\t$target = $( href );\n\t\t\tif ( $target.length ) {\n\t\t\t\tcacheinline[ this.href ] = { link: $(v), target: $target };\n\t\t\t}\n\t\t});\n\n\t\t// handle nav links\n\t\t$toc.delegate( 'a[href^=\"#\"]', 'click', function(e) {\n\t\t\te.preventDefault(); // if you expected return false, *sigh*\n\t\t\tif ( cache[ this.href ] && cache[ this.href ].target ) {\n\t\t\t\t$scrollable.animate( { scrollTop: cache[ this.href ].target.position().top }, 600, 'swing' );\n\t\t\t}\n\t\t});\n\n\t\t//handle inline links\n\t\t$inlinelinks.delegate( 'a[href^=\"#\"]', 'click', function(e) {\n\t\t\te.preventDefault(); // if you expected return false, *sigh*\n\t\t\tif ( cacheinline[ this.href ] && cacheinline[ this.href ].target ) {\n\t\t\t\t$scrollable.animate( { scrollTop: cacheinline[ this.href ].target.offset().top - $navheight }, 600, 'swing' );\n\t\t\t}\n\t\t});\n\n    // Set parallax correctly so it aligns to sidebar\n\n    $parallax1.css(\"right\", ($bodywidth - $headerwidth)/2);\n    $parallax2.css(\"right\", ($bodywidth - $headerwidth)/2);\n    $parallax3.css(\"right\", ($bodywidth - $headerwidth)/2);\n\n\t\t// auto highlight nav links depending on doc position\n\t\tvar deferred = false,\n\t\t\ttimeout = false, // so gonna clear this later, you have NO idea\n\t\t\tlast = false, // makes sure the previous link gets un-activated\n\t\t\tcheck = function() {\n\t\t\t\tvar scroll = $scrollable.scrollTop();\n\n\t\t\t\t$.each( cache, function( i, v ) {\n\t\t\t\t\t// if we're past the link's section, activate it\n\t\t\t\t\tif ( scroll + $navheight >  v.target.position().top  ) {\n\t\t\t\t\t\tlast && last.removeClass('active');\n\t\t\t\t\t\tlast = v.link.addClass('active');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tv.link.removeClass('active');\n\t\t\t\t\t\treturn false; // get outta this $.each\n\t\t\t\t\t}\n\t\t\t\t});\n\n\n\t\t\t\t// all done\n\t\t\t\tclearTimeout( timeout );\n\t\t\t\tdeferred = false;\n\t\t\t};\n\n\t\t// work on scroll, but debounced\n\t\tvar $document = $(document).scroll( function() {\n\n      if($scrollable.scrollTop() > ($originalnavtop - 20)) {\n        $nav.addClass('sticky').css('top', '0');\n      } else {\n        $nav.removeClass('sticky');\n      }\n\n      $parallax1.css(\"opacity\", 0.2 + ($scrollable.scrollTop() / $bodyheight * 0.6));\n      $parallax2.css(\"opacity\", 0.2 + ($scrollable.scrollTop() / $bodyheight * 0.7));\n      $parallax3.css(\"opacity\", 0.2 + ($scrollable.scrollTop() / $bodyheight * 0.4));\n\t\t\t// timeout hasn't been created yet\n\t\t\tif ( !deferred ) {\n\t\t\t\ttimeout = setTimeout( check , 250 ); // defer this stuff\n\t\t\t\tdeferred = true;\n\t\t\t}\n\n\t\t\t$oldscrolltop = $scrollable.scrollTop();\n\n\t\t});\n\n\t\t// fix any possible failed scroll events and fix the nav automatically\n\t\t(function() {\n\t\t\t$document.scroll();\n\t\t\tsetTimeout( arguments.callee, 1500 );\n\t\t})();\n\n    $parallax1.scrollingParallax({staticSpeed: 0.12, reverseDirection: true});\n    $parallax2.scrollingParallax({staticSpeed: 0.1, reverseDirection: true});\n    $parallax3.scrollingParallax({staticSpeed: 0.1, reverseDirection: true});\n\n})( jQuery );\n"
  },
  {
    "path": "js/libs/fittext.js",
    "content": "(function(global, doc, $) {\n\t/*!\t\n\t* FitText.js 1.0\n\t*\n\t* Copyright 2011, Dave Rupert http://daverupert.com\n\t* Released under the WTFPL license \n\t* http://sam.zoy.org/wtfpl/\n\t*\n\t* Date: Thu May 05 14:23:00 2011 -0600\n\t*/\n\n\t$.fn.fitText = function( kompressor, options ) {\n\t\tvar settings = {\n\t\t\t'minFontSize' : Number.NEGATIVE_INFINITY,\n\t\t\t'maxFontSize' : Number.POSITIVE_INFINITY\n\t\t};\n\n\t\treturn this.each(function(){\n\t\t\tvar $this = $(this);              // store the object\n\t\t\tvar compressor = kompressor || 1; // set the compressor\n\n\t\t\tif ( options ) { \n\t\t\t\t$.extend( settings, options );\n\t\t\t}\n\n\t\t\t// Resizer() resizes items based on the object width divided by the compressor * 10\n\t\t\tvar resizer = function () {\n\t\t\t\t$this.css('font-size', Math.max(Math.min($this.width() / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize)));\n\t\t\t};\n\n\t\t\t// Call once to set.\n\t\t\tresizer();\n\n\t\t\t// Call on resize. Opera debounces their resize by default. \n\t\t\t$(window).resize(resizer);\n\n\t\t});\n\t};\n\n})(window, document, jQuery);\n\n(function( $ ){\n\t$('.standout .hed').fitText( 1.05, { minFontSize: '30px', maxFontSize: '80px' });\n\t$('.hed-lead').fitText( 1.25, { minFontSize: '50px', maxFontSize: '150px' });\t\n})( jQuery );\n"
  },
  {
    "path": "js/libs/respond.js",
    "content": "/*! Respond.js v1.0.1pre: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs  */\n(function(e,h){e.respond={};respond.update=function(){};respond.mediaQueriesSupported=h;if(h){return}var u=e.document,r=u.documentElement,i=[],k=[],p=[],o={},g=30,f=u.getElementsByTagName(\"head\")[0]||r,b=f.getElementsByTagName(\"link\"),d=[],a=function(){var B=b,w=B.length,z=0,y,x,A,v;for(;z<w;z++){y=B[z],x=y.href,A=y.media,v=y.rel&&y.rel.toLowerCase()===\"stylesheet\";if(!!x&&v&&!o[x]){if(y.styleSheet&&y.styleSheet.rawCssText){m(y.styleSheet.rawCssText,x,A);o[x]=true}else{if(!/^([a-zA-Z]+?:(\\/\\/)?)/.test(x)||x.replace(RegExp.$1,\"\").split(\"/\")[0]===e.location.host){d.push({href:x,media:A})}}}}t()},t=function(){if(d.length){var v=d.shift();n(v.href,function(w){m(w,v.href,v.media);o[v.href]=true;t()})}},m=function(G,v,x){var E=G.match(/@media[^\\{]+\\{([^\\{\\}]+\\{[^\\}\\{]+\\})+/gi),H=E&&E.length||0,v=v.substring(0,v.lastIndexOf(\"/\")),w=function(I){return I.replace(/(url\\()['\"]?([^\\/\\)'\"][^:\\)'\"]+)['\"]?(\\))/g,\"$1\"+v+\"$2$3\")},y=!H&&x,B=0,A,C,D,z,F;if(v.length){v+=\"/\"}if(y){H=1}for(;B<H;B++){A=0;if(y){C=x;k.push(w(G))}else{C=E[B].match(/@media ([^\\{]+)\\{([\\S\\s]+?)$/)&&RegExp.$1;k.push(RegExp.$2&&w(RegExp.$2))}z=C.split(\",\");F=z.length;for(;A<F;A++){D=z[A];i.push({media:D.match(/(only\\s+)?([a-zA-Z]+)(\\sand)?/)&&RegExp.$2,rules:k.length-1,minw:D.match(/\\(min\\-width:[\\s]*([\\s]*[0-9]+)px[\\s]*\\)/)&&parseFloat(RegExp.$1),maxw:D.match(/\\(max\\-width:[\\s]*([\\s]*[0-9]+)px[\\s]*\\)/)&&parseFloat(RegExp.$1)})}}j()},l,q,j=function(E){var v=\"clientWidth\",x=r[v],D=u.compatMode===\"CSS1Compat\"&&x||u.body[v]||x,z={},C=u.createDocumentFragment(),B=b[b.length-1],w=(new Date()).getTime();if(E&&l&&w-l<g){clearTimeout(q);q=setTimeout(j,g);return}else{l=w}for(var y in i){var F=i[y];if(!F.minw&&!F.maxw||(!F.minw||F.minw&&D>=F.minw)&&(!F.maxw||F.maxw&&D<=F.maxw)){if(!z[F.media]){z[F.media]=[]}z[F.media].push(k[F.rules])}}for(var y in p){if(p[y]&&p[y].parentNode===f){f.removeChild(p[y])}}for(var y in z){var G=u.createElement(\"style\"),A=z[y].join(\"\\n\");G.type=\"text/css\";G.media=y;if(G.styleSheet){G.styleSheet.cssText=A}else{G.appendChild(u.createTextNode(A))}C.appendChild(G);p.push(G)}f.insertBefore(C,B.nextSibling)},n=function(v,x){var w=c();if(!w){return}w.open(\"GET\",v,true);w.onreadystatechange=function(){if(w.readyState!=4||w.status!=200&&w.status!=304){return}x(w.responseText)};if(w.readyState==4){return}w.send(null)},c=(function(){var v=false;try{v=new XMLHttpRequest()}catch(w){v=new ActiveXObject(\"Microsoft.XMLHTTP\")}return function(){return v}})();a();respond.update=a;function s(){j(true)}if(e.addEventListener){e.addEventListener(\"resize\",s,false)}else{if(e.attachEvent){e.attachEvent(\"onresize\",s)}}})(this,(function(f){if(f.matchMedia){return true}var e,i=document,c=i.documentElement,g=c.firstElementChild||c.firstChild,h=!i.body,d=i.body||i.createElement(\"body\"),b=i.createElement(\"div\"),a=\"only all\";b.id=\"mq-test-1\";b.style.cssText=\"position:absolute;top:-99em\";d.appendChild(b);b.innerHTML='_<style media=\"'+a+'\"> #mq-test-1 { width: 9px; }</style>';if(h){c.insertBefore(d,g)}b.removeChild(b.firstChild);e=b.offsetWidth==9;if(h){c.removeChild(d)}else{d.removeChild(b)}return e})(this));"
  },
  {
    "path": "js/libs/storage.js",
    "content": "/*\n See: https://gist.github.com/350433\n*/\nif (typeof window.localStorage == 'undefined' || typeof window.sessionStorage == 'undefined') (function () {\n\nvar Storage = function (type) {\n  function createCookie(name, value, days) {\n    var date, expires;\n\n    if (days) {\n      date = new Date();\n      date.setTime(date.getTime()+(days*24*60*60*1000));\n      expires = \"; expires=\"+date.toGMTString();\n    } else {\n      expires = \"\";\n    }\n    document.cookie = name+\"=\"+value+expires+\"; path=/\";\n  }\n\n  function readCookie(name) {\n    var nameEQ = name + \"=\",\n        ca = document.cookie.split(';'),\n        i, c;\n\n    for (i=0; i < ca.length; i++) {\n      c = ca[i];\n      while (c.charAt(0)==' ') {\n        c = c.substring(1,c.length);\n      }\n\n      if (c.indexOf(nameEQ) == 0) {\n        return c.substring(nameEQ.length,c.length);\n      }\n    }\n    return null;\n  }\n\n  function setData(data) {\n    data = JSON.stringify(data);\n    if (type == 'session') {\n      window.name = data;\n    } else {\n      createCookie('localStorage', data, 365);\n    }\n  }\n\n  function clearData() {\n    if (type == 'session') {\n      window.name = '';\n    } else {\n      createCookie('localStorage', '', 365);\n    }\n  }\n\n  function getData() {\n    var data = type == 'session' ? window.name : readCookie('localStorage');\n    return data ? JSON.parse(data) : {};\n  }\n\n\n  // initialise if there's already data\n  var data = getData();\n\n  return {\n    length: 0,\n    clear: function () {\n      data = {};\n      this.length = 0;\n      clearData();\n    },\n    getItem: function (key) {\n      return data[key] === undefined ? null : data[key];\n    },\n    key: function (i) {\n      // not perfect, but works\n      var ctr = 0;\n      for (var k in data) {\n        if (ctr == i) return k;\n        else ctr++;\n      }\n      return null;\n    },\n    removeItem: function (key) {\n      delete data[key];\n      this.length--;\n      setData(data);\n    },\n    setItem: function (key, value) {\n      data[key] = value+''; // forces the value to a string\n      this.length++;\n      setData(data);\n    }\n  };\n};\n\nif (typeof window.localStorage == 'undefined') window.localStorage = new Storage('local');\nif (typeof window.sessionStorage == 'undefined') window.sessionStorage = new Storage('session');\n\n})();"
  },
  {
    "path": "js/mylibs/.gitignore",
    "content": "!.gitignore\n\n"
  },
  {
    "path": "js/mylibs/touch.js",
    "content": ""
  },
  {
    "path": "js/plugins.js",
    "content": "(function(global) {\n  \n  var $ = global.jQuery;\n\n  $.fn.hashTask = function(o) {\n\n    var defaults = {\n      hashtag: undefined,\n      message: 'oh yeah!',\n      linkSelector: 'a',\n      editTweetText: \"(edit this tweet as you wish. ♡)\"\n    };\n\n    var options = $.extend({}, defaults, o);\n\n    return this.each(function() {\n      var $elem = $(this);\n\n      // The element that will become a twitter pre-fill link.\n      var linkElem = $.isFunction(options.linkSelector)\n            ? options.linkSelector.call($elem)\n            : $elem.find(options.linkSelector);\n\n      // The hashtag used to pre-fill twitter and to search twitter for users.\n      var hashtag = $.isFunction(options.hashtag)\n            ? options.hashtag.call($elem)\n            : $elem.data('hashtag');\n\n      // A message to add to the hash tag.\n      var message = $.isFunction(options.message)\n            ? options.message.call($elem)\n            : options.message;\n\n      // A message to edit the tweet.\n       var editTweetText = $.isFunction(options.editTweetText)\n            ? options.editTweetText.call($elem)\n            : options.editTweetText;\n\n      // A URL that will pre-fill a twitter status message.\n      var prefillUrl = 'https://twitter.com/intent/tweet?text=' + encodeURIComponent(message + ' ' + hashtag + ' ' + editTweetText);\n\n      linkElem.attr('href', prefillUrl);\n    });\n  };\n\n})(window);\n\n/**\n * jQuery Scrolling Parallax v0.1\n * http://jonraasch.com/blog/scrolling-parallax-jquery-plugin\n *\n * Copyright (c) 2009 Jon Raasch (http://jonraasch.com/)\n * Licensed under the FreeBSD License (See terms below)\n *\n * @author Jon Raasch\n *\n * @projectDescription    jQuery plugin to create a parallax effect when the page is scrolled.\n *\n * @version 0.1.0\n *\n * @requires jquery.js (v 1.3.2 minimum)\n *\n *\n * TERMS OF USE - jQuery Scrolling Parallax\n * Open source under the FreeBSD License.\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n *    1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *    2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY JON RAASCH ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JON RAASCH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of Jon Raasch, who is the man.\n *\n *\n * FOR USAGE INSTRUCTIONS SEE THE DOCUMENATION AT: http://dev.jonraasch.com/scrolling-parallax/documentation\n *\n *\n */\n\n\n( function( $ ) {\n\n    $.scrollingParallax = function ( box, options )\n    {\n        var options = options || {};\n\n        // vertical options\n\n        options.enableVertical = typeof( options.enableVertical ) != 'undefined' ? options.enableVertical : true;\n\n        if ( options.enableVertical ) {\n            options.staticSpeed = options.staticSpeed || false;\n            options.staticScrollLimit = typeof(options.staticScrollLimit) != 'undefined' ? options.staticScrollLimit : true;\n\n            options.loopIt = options.loopIt || false;\n\n            options.reverseDirection = options.reverseDirection || false;\n        }\n\n        // horizontal options\n\n        options.enableHorizontal = options.enableHorizontal || false;\n\n        if ( options.enableHorizontal ) {\n            options.staticSpeedX = options.staticSpeedX || false;\n            options.staticScrollLimitX = typeof(options.staticScrollLimitX) != 'undefined' ? options.staticScrollLimitX : true;\n\n            options.loopItX = options.loopItX || false;\n\n            options.reverseDirectionX = options.reverseDirectionX || false;\n        }\n\n        // IE6 options\n\n        options.disableIE6 = options.disableIE6 || false; // disables in IE6 altogether\n        options.disableIE6Anim = typeof(options.disableIE6Anim) != 'undefined' ? options.disableIE6Anim : true; // disables IE6 animation, however background will still append\n\n        // layout options\n\n        options.bgWidth = options.bgWidth || (options.enableHorizontal ? '150%' : '100%' );\n        options.bgHeight = options.bgHeight || '150%';\n\n        options.bgRepeat = options.bgRepeat || false;\n\n        options.appendInFront = options.appendInFront || false;\n\n        options.parallaxHeight = options.parallaxHeight || false;\n        options.parallaxWidth = options.parallaxWidth || false;\n\n\n        var isIE6 = $.browser.msie && $.browser.version < 7 ? true : false;\n\n        if ( options.disableIE6 && isIE6 ) return false;\n\n        var $document = $(document);\n        var $window   = $(window);\n        var $box;\n\n        var backgroundMode = false;\n\n        if ( options.enableVertical ) {\n            var boxHeight;\n            var windowHeight;\n            var docHeight;\n            var parallaxRoom;\n            var maxIE6Move = 0;\n            var loopCount = 0;\n            var startingPos = 0;\n            var tooSmallMode = false;\n            var oldMoveIt = null;\n        }\n\n        if ( options.enableHorizontal ) {\n            var boxWidth;\n            var windowWidth;\n            var docWidth;\n            var parallaxRoomX;\n            var maxIE6MoveX = 0;\n            var loopCountX = 0;\n            var startingPosX = 0;\n            var tooSmallModeX = false;\n            var oldMoveItX = null;\n        }\n\n        init( box );\n\n\n\n        // init( obj/string box )   :  sets up the parallax and associated events\n\n        function init( box ) {\n            // if string append image as background, otherwise define as jQuery object\n            if ( typeof( box ) == 'string' ) $box = appendBackground( box );\n            else {\n                $box = $( box );\n\n                $box.css('position', isIE6 ? 'absolute' : 'fixed');\n\n                if ( options.enableVertical ) startingPos = parseInt( $box.css('top') );\n\n                if ( options.enableHorizontal ) startingPosX = parseInt( $box.css('left') );\n            }\n\n            if ( options.disableIE6Anim && isIE6 ) return false;\n\n            defineSizes();\n\n            // if in background mode, and reverseDirection, then attch the background to the opposite end to maximize scrolling room\n            if ( backgroundMode ) {\n                if ( options.reverseDirection && options.enableVertical ) {\n                    startingPos += -1 * parallaxRoom;\n                    $box.css('top', startingPos);\n                }\n\n                if ( options.reverseDirectionX && options.enableHorizontal ) {\n                    startingPosX += -1 * parallaxRoomX;\n                    $box.css('left', startingPosX);\n                }\n            }\n\n            // attach scroll and resize events\n\n            $window.scroll( function() {\n                ani();\n            });\n\n            $window.resize( function() {\n                defineSizes();\n            });\n        }\n\n\n\n\n        // appendBackground( string theSrc )  :   appends an image to the page as a stretched background\n\n        function appendBackground( theSrc ) {\n            var bgCss = {\n                display:   'block',\n                top:       0,\n                left:      0,\n                width:     options.bgWidth,\n                height:    options.bgHeight,\n                zIndex:    0\n            };\n\n            bgCss.position = isIE6 ? 'absolute' : 'fixed';\n\n            if ( options.bgRepeat ) {\n                var $obj = options.appendInFront ? $('<div></div>').appendTo( $('body') ) : $('<div></div>').prependTo( $('body') );\n                bgCss.backgroundRepeat = 'repeat';\n                bgCss.backgroundImage  = 'url(\"' + theSrc + '\")';\n            }\n            else {\n                var $obj = options.appendInFront ? $('<img />').appendTo( $('body') ) : $('<img />').prependTo( $('body') );\n                $obj.attr('src', theSrc);\n            }\n\n\n            $obj.css( bgCss );\n\n            backgroundMode = true;\n\n            return $obj;\n        }\n\n\n\n\n        // defineSizes()  :  sets up various constants used by the app - must be set on page load and on screen resize\n\n        function defineSizes() {\n\n            // define vertical vars\n\n            if ( options.enableVertical ) {\n                boxHeight = $box.height();\n                windowHeight = $window.height();\n                docHeight = $document.height();\n\n                parallaxRoom = ( options.parallaxHeight || boxHeight ) - windowHeight;\n\n                // if parallax object is smaller than window size\n                if ( parallaxRoom < 0 ) {\n                    if ( options.staticSpeed ) parallaxRoom = windowHeight -  boxHeight;\n                    else parallaxRoom = options.reverseDirection ? windowHeight - startingPos - boxHeight : startingPos;\n\n                    tooSmallMode = true;\n                }\n\n                if ( isIE6 && !maxIE6Move ) maxIE6Move =  -1 * ( docHeight - boxHeight );\n\n                if ( options.loopIt ) loopCount = parseInt( $document.scrollTop() / ( tooSmallMode ? windowHeight : boxHeight ) );\n            }\n\n            // define horizontal vars\n\n            if ( options.enableHorizontal ) {\n                boxWidth = $box.width();\n                windowWidth = $window.width();\n                docWidth = $document.width();\n\n                parallaxRoomX = ( options.parallaxWidth || boxWidth ) - windowWidth;\n\n                // if parallax object is smaller than window size\n                if ( parallaxRoomX < 0 ) {\n                    parallaxRoomX = options.staticSpeedX ? windowWidth - boxWidth : options.reverseDirectionX ? windowWidth - startingPosX - boxWidth : startingPosX;\n\n                    tooSmallModeX = true;\n                }\n\n                if ( isIE6 && !maxIE6MoveX ) maxIE6MoveX =  -1 * ( docWidth - boxWidth );\n\n                if ( options.loopItX ) loopCountX = parseInt( $document.scrollLeft() / ( tooSmallModeX ? windowWidth : boxWidth ) );\n            }\n\n            // make any changes\n            ani();\n        }\n\n\n\n        // ani()  :  performs the animation of the object\n\n        function ani() {\n\n            // dont let multiple animations queue up\n            $box.queue( [ ] );\n\n            var theCss = {};\n\n\n            // vertical\n            if ( options.enableVertical ) {\n\n                var moveIt = calculateMove(true);\n\n                theCss.top = moveIt;\n            }\n\n\n            // horizontal\n            if ( options.enableHorizontal ) {\n\n                var moveItX = calculateMove(false);\n\n                theCss.left = moveItX;\n            }\n\n            // if large move animate in FF, safari and opera for smoother transition\n            if ( !$.browser.msie && ( Math.abs( oldMoveIt - moveIt ) > 100 || Math.abs( oldMoveItX - moveItX ) > 100 ) ) $box.animate(theCss, 30);\n            else $box.css(theCss);\n\n            oldMoveIt = moveIt;\n            oldMoveItX = moveItX;\n\n        }\n\n\n\n        // calculateMove( boolean vertical ) : determines amount to move whether vertically or horizontally\n\n        function calculateMove( vertical ) {\n            // establish variables, this is basically a switch between vertical and horizontal modes\n            if ( vertical ) {\n                var offset =  $document.scrollTop();\n                var docSize = docHeight;\n                var windowSize = windowHeight;\n                var boxSize = boxHeight;\n\n                var parallaxRoom2 = parallaxRoom;\n\n                var loopCount2 = loopCount;\n                var startingPos2 = startingPos;\n                var parallaxRoom2 = parallaxRoom;\n                var tooSmallMode2 = tooSmallMode;\n                var maxIE6Move2 = maxIE6Move;\n\n                var opts = {\n                    reverseDirection : options.reverseDirection,\n                    staticSpeed : options.staticSpeed,\n                    loopIt : options.loopIt,\n                    staticScrollLimit : options.staticScrollLimit\n                }\n            }\n            else {\n                var offset = $document.scrollLeft();\n                var docSize = docWidth;\n                var windowSize = windowWidth;\n                var boxSize = boxWidth;\n\n                var loopCount2 = loopCountX;\n                var startingPos2 = startingPosX;\n                var parallaxRoom2 = parallaxRoomX;\n                var tooSmallMode2 = tooSmallModeX;\n                var maxIE6Move2 = maxIE6MoveX;\n\n                var opts = {\n                    reverseDirection : options.reverseDirectionX,\n                    staticSpeed : options.staticSpeedX,\n                    loopIt : options.loopItX,\n                    staticScrollLimit : options.staticScrollLimitX\n                }\n            }\n\n            /*** get move amount - static speed ***/\n\n            if ( opts.staticSpeed ) {\n                var move = offset * opts.staticSpeed;\n\n                // account for number of loops\n                move -= parallaxRoom2 * ( loopCount2 );\n            }\n\n            /*** get move amount - auto speed ***/\n\n            else {\n                // determine percentage of page that has been scrolled down\n                var offsetPercent = offset / ( docSize - windowSize );\n\n                /*\n                var moveIt = ( $.browser.msie && $.browser.version < 7 )\n                    ? -1 * ( offsetParent * parallaxRoom + offsetTop )\n                    : -1 * offsetPercent * parallaxRoom;\n                */\n\n                var move = offsetPercent * parallaxRoom2;\n            }\n\n            // reverse direction\n            if ( !opts.reverseDirection ) move *= -1;\n\n            // incorporate starting position\n            move += startingPos2;\n\n            // if static speed set, make sure move is within bounds\n            if ( opts.staticSpeed ) move = checkMove( move, vertical, opts, parallaxRoom2, tooSmallMode2 );\n\n\n            // if in tooSmallMode and looping, add difference of window height and box height, since the box needs to be conceptualized as that much taller ( otherwise it would loop in place rather than over the screen )\n            if ( tooSmallMode2 && opts.staticSpeed && opts.loopIt ) move += windowSize - boxSize;\n\n            if ( isIE6 ) {\n                // IE6 fix for fixed positioning\n                move += offset;\n                move = Math.max( parseInt(move), parseInt(maxIE6Move2) );\n            }\n\n            return move;\n        }\n\n\n\n        // checkMove( int moveIt )  :  checks to ensure that move amount does not exceed established bounds\n\n        function checkMove( move, vertical, opts, parallaxRoom, tooSmallMode ) {\n\n            // if overflow limited\n            if ( !opts.loopIt ) {\n                if ( opts.staticScrollLimit ){\n                    if ( tooSmallMode ) {\n                        if ( move < 0 ) move = 0;\n                        if ( move > parallaxRoom ) move = parallaxRoom;\n                    }\n                    else {\n                        if ( move > 0 ) move = 0;\n                        if ( -1 * move > parallaxRoom ) move = -1 * parallaxRoom;\n                    }\n                }\n            }\n\n            // if overflow loops\n            else {\n                while ( move < parallaxRoom ) {\n                    move += parallaxRoom;\n\n                    var loopCountChange = opts.reverseDirection ? -1 : 1;\n\n                    if ( vertical ) loopCount += loopCountChange;\n                    else loopCountX += loopCountChange;\n                }\n\n                while ( move > ( opts.reverseDirection ? -1 : 0 ) ) {\n                    move -= parallaxRoom;\n\n                    var loopCountChange = opts.reverseDirection ? -1 : 1;\n\n                    if ( vertical ) loopCount -= loopCountChange;\n                    else loopCountX -= loopCountChange;\n                }\n            }\n\n            return move;\n        }\n    };\n\n    $.fn.scrollingParallax = function ( options )\n    {\n\n        this.each( function()\n            {\n                new $.scrollingParallax( this, options );\n            }\n        );\n\n        return this;\n    };\n})( jQuery );\n"
  },
  {
    "path": "pt-br/index.html",
    "content": "<!DOCTYPE html public \"i ♥ the web\">\n<!--[if lt IE 9]>      <html class=\"no-js oldie no-fontface\" lang=\"en\"> <![endif]-->\n<!--[if gt IE 8]><!--> <html class=\"no-js no-fontface\" lang=\"pt\">   <!--<![endif]-->\n<head>\n    <meta charset=\"utf-8\">\n    <title>Move The Web Forward | Guia de como se envolver com os padrões e melhoras dos navegadores</title>\n    <meta name=\"description\" content=\"What you can do as a front-end developer\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, minimum-scale=1\">\n\n    <!-- For iPhone 4 with high-resolution Retina display: -->\n    <link rel=\"apple-touch-icon-precomposed\" sizes=\"114x114\" href=\"apple-touch-icon-114x114-precomposed.png\">\n    <!-- For first-generation iPad: -->\n    <link rel=\"apple-touch-icon-precomposed\" sizes=\"72x72\" href=\"apple-touch-icon-72x72-precomposed.png\">\n    <!-- For non-Retina iPhone, iPod Touch, and Android 2.1+ devices: -->\n    <link rel=\"apple-touch-icon-precomposed\" href=\"apple-touch-icon-precomposed.png\">\n\n    <link rel=\"stylesheet\" href=\"../css/style.css\">\n\n    <!-- Should be combined: -->\n    <script src=\"../js/libs/modernizr.min.js\"></script>\n    <script src=\"../js/controller.js\"></script>\n</head>\n\n<body>\n  <b class=\"gimmick\"><i></i><i></i><i></i></b>\n    <header class=\"col-ab\">\n        <div class=\"lead\">\n            <h1 class=\"hed-lead\">Leve a web adiante<span></span></h1>\n            <h2 class=\"subhed-lead\">Você pode fazer a web ser tão incrível quanto você quiser!</h2>\n            <p class=\"subhed\">Você é fã dos padrões web. Você quer retribuir isso à comunidadeo. Quer saber por onde começar? <b>Nós estamos aqui para ajudar.</b></p>\n        </div>\n        <div class=\"col-split\">\n            <p>Seja você um desenvolvedor web talentoso, alguém que se vira desde os tempos de tabelas e tags <code>font</code>, ou apenas um hacker em tempo livre, há várias maneiras de contribuir. Abaixo há uma lista de algumas formas para qualquer um retribuir à plataforma web.\n            <p>Nossa meta é facilitar para que qualquer um possa contribuir para a plataforma, seja aprendendo mais sobre como funciona, ensinando outros ou redigindo especificações. A web cresceu por causa de gente como você, e nós queremos viabilizar para que todos possam retribuir.\n            <p style=\"font-size:90%\">Também disponível em <a href=\"/\">English</a>, <a href=\"/ar\">عربى</a> e <a href=\"/cn\">中文</a>.\n            </p>\n        </div>\n    </header>\n\n    <div id=\"nav_container\">\n      <nav id=\"toc\">\n        <ul>\n          <li><a href=#levelup>Primeiros passos</a></li>\n          <li><a href=#digdeep>Se aprofundando</a></li>\n          <li><a href=#virtuoso>Garoto pródigo</a></li>\n        </ul>\n      </nav>\n    </div>\n\n    <article class=\"section\">\n        <div class=\"standout\" id=levelup>\n            <h1 class=\"hed\">Primeiros passos</h1>\n            <h2 class=\"subhed\">Você é bom no que faz. Entre para a comunidade!</h2>\n        </div>\n\n        <section id=\"learn\" class=\"col-ab\">\n            <div class=\"col-a\">\n              <h1 class=\"hed\">Aprenda</h1>\n              <p>Uma das coisas mais belas da web é sua metamorfose constante. Essas mudanças e melhoras podem ser difíceis de acompanhar, nós estamos aqui para ajudar você a não ficar pra trás! Vamos listar alguns recursos que vão lhe mostrar como os navegadores funcionam, e como ficar a par de suas modificações. Nota: os sites, por hora, estão disponíveis apenas em inglês.</p>\n\n              <h2 id=\"how_do_i_keep_up_with_what8217s_landing_in_browsers\" class=\"subhed\">Como eu me mantenho atualizado com o que acontece nos navegadores?</h2>\n              <ul>\n                <li><a href=\"http://updates.html5rocks.com/2011/10/Keeping-up-with-HTML5-and-browser-support\">Keeping up with HTML5 and browser support</a> - uma lista de recursos que agrupam todas as mudanças</li>\n                <li><a href=\"http://peter.sh/\">Blog de Peter Beverloo</a> - atualizações semanais do Webkit e Chrome</li>\n                <li><a href=\"http://blog.whatwg.org/\">The WHATWG Blog</a> - sumário das atividades semanais de web standard</li>\n                <li><a href=\"http://www.w3.org/QA/archive/open_web/\">W3C&#8217;s open web</a> - atualizações semanais da plataforma Open Web</li>\n                <li><a href=\"http://my.opera.com/ODIN/blog/\">Opera Developer News</a> - lista as mudanças da plataforma web Opera\n                <li><a href=\"http://updates.html5rocks.com\">HTML5 Rocks updates</a> - Novidades de HTML5 e Chrome\n\n                <li><a href=\"http://hacks.mozilla.org/\">Mozilla Hacks</a> - aplicativos legais e funcionalidades HTML5\n                <li><a href=\"http://blogs.msdn.com/b/ie/\">Blog IE</a> - atualizações para o IE\n              </ul>\n\n              <h3 id=\"follow_them_on_twitter\" class=\"subhed\">Siga-os no Twitter</h3>\n                <p>\n                  Recomendamos seguir: <a href=\"http://twitter.com/oDevRel\">@oDevRel</a> (Relacionamento com desenvolvedores Opera), <a href=\"http://twitter.com/ChromiumDev\">@ChromiumDev</a> (Relacionamento com desenvolvedores Chrome), <a href=\"http://twitter.com/mozhacks\">@mozhacks</a> (Ponto de desenvolvedores Mozilla) & <a href=\"http://twitter.com/ie\">@IE</a> (Equipe do Internet Explorer).\n                </p>\n\n              <h2 id=\"how_do_i_understand_how_browsers_work\" class=\"subhed\">Como entender o funcionamento dos navegadores?</h2>\n\n              <ul>\n                <li><a href=\"http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/\">How Browsers Work: Behind the Scenes of Modern Web Browsers</a> - Explicação aprofundada de como os navegadores funcionam</li>\n                <li><a href=\"http://ontwik.com/javascript/txjs-2011-a9-alex-russell-life-of-a-button-element/?utm_source=feedburner&utm_medium=twitter&utm_campaign=Feed%3A+Ontwik+%28Ontwik%29\">Life of a &lt;button> element (por Alex Russell)</a> - excelente palestra sobre renderização e CSS</li>\n              </ul>\n\n              <h2 id=\"other_learning_resources\" class=\"subhed\">Outras fontes de aprendizado</h2>\n\n              <ul>\n                <li><a href=\"http://css-tricks.com\">CSS-tricks</a> - fornece uma gama de artigos, tutoriais, e downloads para a comunicade de web design.</li>\n                <li><a href=\"http://html5doctor.com\">HTML5doctor</a> - excelente fonte para pessoas que querem aprender sobre HTML5, sua semântica e como implementá-lo hoje!</li>\n                <li><a href=\"http://diveintohtml5.info/\">Dive into HTML5</a> - dá uma visão aprofundada de algumas funcionalidades de HTML5.</li>\n                <li><a href=\"http://addyosmani.com/blog/\">Blog de Addy Osmani&#8217;s</a> - muitos artigos excelentes para pessoas que querem saber mais sobre jQuery, JavaScript, HTML5, e CSS3.</li>\n                <li><a href=\"http://paulirish.com\">Blog de Paul Irish&#8217;s</a> - tudo para fazer websites legais e mantê-lo atualizado com as novidades mais recentes.</li>\n                <li><a href=\"http://dev.opera.com\">Dev.Opera</a> - artigos para aprender sobre funcionalidades HTML5.</li>\n                <li><a href=\"http://paulirish.com/2011/web-browser-frontend-and-standards-feeds-to-follow/\">Feeds de navegadores, front-ends e padrões para seguir</a> </li>\n                <li><a href=\"http://yuilibrary.com/theater/\">YUI Theater</a> - vídeos de palestras de engenheiros front-end sobre as tecnologias web ministrados no Yahoo! ao longo dos anos (muitos não ligados ao YUI).</li>\n                <li><a href=\"http://www.adobe.com/devnet/html5.html\">Adobe Developer Connection</a> - artigos e vídeos para apbrender sobre HTML5, CSS3 e desenvolvimento móvel.</li>\n              </ul>\n\n              <h2 id=\"reference_docs_wikis\" class=\"subhed\">Guias de referência/wikis</h2>\n\n              <ul>\n                <li><a href=\"https://developer.mozilla.org/en-US/\">Mozilla&#8217;s MDN</a> - excelente documentação relacionada a HTML, CSS, JavaScript, o DOM, e mais. É também um ótimo lugar para contribuir! Leia <a href=\"https://developer.mozilla.org/Project:en/How_to_Help\">Como ajudar</a> e aprenda como  <a href=\"https://developer.mozilla.org/Project:en/Getting_started\">começar</a>.</li>\n                <li><a href=\"https://developer.mozilla.org/Writing_Forward_Compatible_Websites\">Forward-compatible websites</a> - lista de melhores práticas para criar sites que não vão quebrar quando os navegadores forem atualizados.</li>\n                <li><a href=\"http://html5please.com/\">HTML5 Please - Use new and shiny responsibly</a> - Enciclopédia para ferramentas HTML5 nos navegadores, veja funcionalidades específicas e quando/se você pode usar.</li>\n              </ul>\n          </div>\n          <div class=\"col-b\">\n            <section class=\"getinvolved\">\n              <h2 class=\"subhed\">Se coçando pra aprender?</h2>\n              <div class=\"task\" data-hashtag=\"#learn\">\n                  <p>Tudo que você precisa fazer é dar uma lida rápida em alguns artigos ou tweets e você já estará encaminhado! Acredite em nós &ndash; depois do primeiro passo tudo fica mais fácil.</p>\n                  <a href=\"#\" class=\"pledge\">Sim, eu quero fazer parte!</a>\n                  <div class=\"pledges\"><p>Veja outras pessoas que também estão interessadas:</p></div>\n              </div>\n            </section>\n          </div>\n          </section>\n\n        <section id=\"meetups\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">Conheça pessoas que pensam como você</h1>\n            <p>Participar de reuniões e conferências na sua região é um ótimo jeito de entrar em contato com outros desenvolvedores para aprender, trocar conhecimento, e trazer novas idéias e colaborações à vida. Sites como <a href=\"http://meetup.com\">Meetup</a> e <a href=\"http://lanyrd.com\">Lanyrd</a> podem lhe ajudar a encontrar eventos na sua região.</p>\n          </div>\n        </section>\n        <section id=\"askhelp\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">Peça ajuda</h1>\n            <h2 id=\"answer_questions_and_participate_in_conversations_on_irc\" class=\"subhed\">Responda perguntas e participe de conversas no IRC</h2>\n            <p><a href=\"http://richard.esplins.org/siwi/2011/07/08/getting-started-freenode-irc/\">Iniciando o uso de freenode e irc</a></p>\n            <ul>\n              <li><b>Canais Freenode IRC:</b> #html5 / #css / #javascript / #whatwg / #jquery / #yui / #dojo / #web / <span title=\"browser based game development\">#bbg</span> (on <a href=\"http://webchat.freenode.net\">irc.freenode.net</a>) </li>\n              <li id=\"mozilla_irc\"><b>Canal IRC Mozilla:</b> #js (on <a href=\"http://irc.mozilla.org\">irc.mozilla.org</a>)</li>\n            </ul>\n\n            <h2 id=\"how_to_ask_for_help\" class=\"subhed\">Como pedir ajuda</h2>\n            <ol class=\"tasks\">\n              <li>Você provavelmente deve <a href=\"https://css-tricks.com/seriously-just-make-a-jsfiddle/\">criar um jsfiddle</a>.</li>\n              <li><a href=\"https://css-tricks.com/reduced-test-cases/\">Crie um caso de teste reduzido</a>.</li>\n              <li>Lembre-se: seja específico!</li>\n              <li>Pergunte no IRC, <a href=\"http://stackoverflow.com\">StackOverflow</a> (mesmo no <a href=\"http://chat.stackoverflow.com/rooms/17/javascript\">bate-papo javascript</a>), ou para um grupo de amigos.\n            </ol>\n          </div>\n\n          <div class=\"col-b\">\n\t        <section class=\"getinvolved\">\n              <h2 class=\"subhed\">Uma mãozinha</h2>\n              <div class=\"task\" data-hashtag=\"#ask4help\">\n                <p>Todos chegamos onde estamos pois contamos com a ajuda de outros vez ou outra. Não tenha vergonha, apenas pergunte! Só por favor faça um jsfiddle antes. =D</p>\n                <a href=\"#\" class=\"pledge\">Sim, eu quero fazer parte!</a>\n                <div class=\"pledges\"><p>Veja outras pessoas que também estão interessadas:</p></div>\n              </div>\n             </section>\n          </div>\n        </section>\n    </article>\n\n    <article class=\"section\">\n        <div class=\"standout\" id=digdeep>\n            <h1 class=\"hed\">Vá fundo</h1>\n            <h2 class=\"subhed\">Você certamente já sabe se virar. Agora é hora de mostrar.</h2>\n        </div>\n        <section id=\"helpothers\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">Ajude outros</h1>\n            <p>Todos tivemos que começar em algum lugar! Prestar auxílio ajuda a reforçar seu conhecimento, e contribui para expandir os conceitos aos quais você se expôs. Listamos abaixo alguns grandes exemplos de projetos open-source que estão sempre precisando de ajuda. Lembre-se - tudo vale a pena quando a alma não é pequena!</p>\n            <h2 id=\"open_source_projects_worth_your_time\" class=\"subhed\">Projetos Open-Source que valem a pena dar uma olhada</h2>\n\n            <ul>\n              <li><a href=\"http://github.com/h5bp/html5-boilerplate\">HTML5 Boilerplate</a> <span>- um ponto de partida para desenvolvedores frontend levando em consideração as boas práticas</span>\n              <li><a href=\"https://github.com/jquery/learn.jquery.com\">jQuery Learning Site</a> <span>- site educacional para a popular biblioteca jQuery</span>\n              <li><a href=\"https://github.com/jquery/jquery-mobile\">jQuery Mobile</a> <span>- melhores práticas para aprimoramento progressivo de plataforma móvel</span>\n              <li><a href=\"https://github.com/Modernizr/Modernizr\">Modernizr</a> <span>- a cereja do bolo em detecção de funcionalidades</span>\n              <li><a href=\"https://github.com/twbs/bootstrap\">Bootstrap</a> <span>- um conjunto de ferramentas de css e js que serve como pontapé inicial para webapps</span>\n              <li><a href=\"http://necolas.github.com/normalize.css/\">Normalize.css</a> <span>- faça todos os navegadores renderizar o conteúdo da mesma forma</span>\n              <li><a href=\"http://dojotoolkit.org/get-involved\">Dojo</a> <span>- conjunto de ferramentas para frontend de fácil compreensão</span>\n              <li><a href=\"https://github.com/paulirish/lazyweb-requests/issues?state=open\">Lazyweb requests</a> <span>- Ferramentas web e soluções que seria gostaríamos de ter como desenvolvedores web.</span>\n            </ul>\n            <p>Faça o que pedimos em <a href=\"#how_to_ask_for_help\">&#8216;peça ajuda&#8217;</a> ali em cima e assista ao <a href=\"http://addyosmani.com/blog/getting-involved-with-open-source/\">podcast de Addy Osmani&#8217;s sobre como fazer parte</a>!</p>\n\n          </div>\n\n          <div class=\"col-b\">\n            <section class=\"getinvolved\">\n              <h2 class=\"subhed\">Passe adiante!</h2>\n              <div class=\"task\" data-hashtag=\"#helpothers\">\n                <p>Ler código bem feito leva a escrever código bem feito. Dê uma olhada nos ótimos projetos que listamos abaixo, e ajude-os a se tornarem ainda melhores do que já são.</p>\n                <a href=\"#\" class=\"pledge\">Sim, eu quero fazer parte!</a>\n                <div class=\"pledges\"><p>Veja outras pessoas que também estão interessadas:</p></div>\n              </div>\n            </section>\n          </div>\n        </section>\n\n        <section id=\"specs\" class=\"col-ab\">\n            <div class=\"col-a\">\n                <h1 class=\"hed\">Dê feedback das especificações</h1>\n\n                <p>Especificações ditam o comportamento esperado. Elas são criadas por Working Groups (WG) em conjunto com discussões ativas em listas de e-mail. Mesmo não tendo certeza se todos os navegadores irão aderir às regras ditadas nas especificações, elas nos fornecem algo que nós, desenvolvedores, podemos padronizar em cima.</p>\n\n                <ul>\n                    <li>Aprenda a <a href=\"http://diveintohtml5.info/past.html\">história do HTML</a>.</li>\n                    <li>Dê uma olhada em <a href=\"http://fantasai.inkedblade.net/weblog/2011/inside-csswg/\">como os WG de CSS funcionam</a>.</li>\n                    <li>Inscreva-se a estas listas para seguir e contribuir às discussões que guiam a web:\n                        <ul class=\"resources\">\n                            <li><a href=\"http://lists.w3.org/Archives/Public/public-webapps/\">public-webapps</a> -  discussões técnicas do Web Applications Working Group</li>\n                            <li><a href=\"http://lists.w3.org/Archives/Public/www-style/\">www-style</a> - discussões técnias do Cascading Style Sheets (CSS) e suas especificações</li>\n                            <li><a href=\"http://lists.whatwg.org/pipermail/whatwg-whatwg.org/\">whatwg</a> - lista de e-mails do WHATWG</li>\n                            <li><a href=\"http://lists.w3.org/Archives/Public/public-html/\">public-html</a> - WG do W3C HTML</li>\n                            <li><a href=\"http://lists.w3.org/Archives/Public/www-dom/\">www-dom</a> - onde o DOM é melhorado</li>\n                            <li><a href=\"http://lists.w3.org/Archives/Public/public-fx/\">public-fx</a> - questões relacionadas ao WGs de CSS e SVG</li>\n                        </ul>\n                    </li>\n                    <li>Leia toda a <a href=\"http://developers.whatwg.org/\">especificação HTML5 para desenvolvedores</a> (sem questões de implementação, formatada lindamente para você).</li>\n                    <li>A melhor forma de comentar ou dar feedback nos conteúdos das <a href=\"http://www.whatwg.org/specs/web-apps/current-work/multipage/\">especificações do HTML</a> é escolher o texto em que você deseja enviar seu comentário e deixar uma mensagem no formulário localizado no rodapé da página.</li>\n                    <li>\n                        Veja os últimos commits nas especificações do HTML e CSS seguindo seus respectivos WGs no Twitter:\n                        <ul class=\"resources\">\n                            <li><a href=\"http://twitter.com/whatwg\">@whatwg</a></li>\n                            <li><a href=\"http://twitter.com/csscommits\">@csscommits</a></li>\n                        </ul>\n                    </li>\n                </ul>\n            </div>\n            <div class=\"col-b\">\n              <section class=\"getinvolved\">\n                <h2 class=\"subhed\">Está sacando das especificações?</h2>\n                <div class=\"task\" data-hashtag=\"#feedback\">\n                  <p>Nós somos os caras usando as especificações, então por que não ajudar a criar as especificações que amamos? Vamos defender os padrões, e torná-los ainda melhores!</p>\n                  <a href=\"#\" class=\"pledge\">Sim, eu quero fazer parte!</a>\n                  <div class=\"pledges\"><p>Veja outras pessoas que também estão interessadas:</p></div>\n                </div>\n              </section>\n            </div>\n        </section>\n\n        <section id=\"explore\" class=\"col-ab\">\n            <div class=\"col-a\">\n              <h1 class=\"hed\">Explore funcionalidades frontend</h1>\n              <p>Depois de ter passado pelo básico, é hora de ir um pouco mais fundo nos web standards atuais e futuros! Tudo em ritmo de festa, pois aqui, nós vemos CSS avançado, funções/APIs HTML5 novinhas em folha  e também o futuro do que estas linguagens se tornarão. Muitos novos caminhos estão agora disponíveis nos navegadores, e explorar estes caminhos nos ajudará a levar a web adiante!</p>\n\n            <h2 id=\"examples_of_how_to_explore_features_well\" class=\"subhed\">Exemplos de como explorar bem as funcionalidades</h2>\n            <ul>\n              <li><a href=\"http://perfectionkills.com/global-eval-what-are-the-options/\">Global <code>eval</code>: what are the options?</a> <span> - kangax</span>\n              <li><a href=\"http://nicolasgallagher.com/multiple-backgrounds-and-borders-with-css2/\">Multiple Backgrounds and Borders with CSS 2.1</a> <span> - Nicolas Gallagher</span>\n              <li><a href=\"http://nicolasgallagher.com/css-background-image-hacks/\">CSS background-image hacks</a> <span> - Nicolas Gallagher</span>\n              <li><a href=\"http://www.webdirections.org/blog/let-the-web-move-you-css3-animations-and-transitions/\">Let the Web move you — CSS3 Animations and Transitions</a> <span> - John Allsopp</span>\n              <li><a href=\"http://addyosmani.com/largescalejavascript/\">Patterns For Large-Scale JavaScript Application Architecture</a> <span> - Addy Osmani</span>\n              <li><a href=\"http://designfestival.com/the-cicada-principle-and-why-it-matters-to-web-designers/\">The Cicada Principle and why it matters to web designers</a> <span> - Alex Walker</span>\n              <li><a href=\"http://css-tricks.com/snippets/css/webkit-keyframe-animation-syntax/\">Keyframe animation syntax</a> <span> - Chris Coyier</span>\n              <li><a href=\"http://www.blog.highub.com/css/whats-new-in-css-selectors-level-4/\">What's new in CSS Selectors (Level 4)</a> <span> - Shi Chuan</span>\n              <li><a href=\"http://mathiasbynens.be/notes/touch-icons\">Everything you always wanted to know about touch icons</a> <span> - Mathias Bynens</span>\n              <li><a href=\"http://coding.smashingmagazine.com/2009/09/15/the-z-index-css-property-a-comprehensive-look/\">The z-index CSS Property: A Comprehensive Look</a> <span> - Louis Lazaris</span>\n            </ul>\n\n            <h2 id=\"cool_ideas_to_explore_more\" class=\"subhed\">Coisas legais para explorar mais (e escrever a respeito)</h2>\n\n            <p>Os navegadores estão lançando novas funcionalidades toda hora. Os prefixos que nós amamos odiar estão lá para que os desenvolvedores possam prestar feedback de como a funcionalidade atende suas necessidades. Tome coragem de ver se elas atendem! A visão geral de <a href=\"http://peter.sh/experiments/vendor-prefixed-css-property-overview/\">vendor-prefixed CSS</a>, por Peter Beverloo, tem um monte de CSS experimental; muitos deles ainda não totalmente compreendidos. Pense em escrever sobre todos os ítens abaixo:\n\n              <ul>\n                <li><a href=\"https://developer.mozilla.org/En/CSS/%3Achecked\">The :checked selector</a> / <a href=\"http://dev.w3.org/csswg/css3-images/#object-fit\">object-fit</a>  / <a href=\"https://developer.mozilla.org/en/CSS/background-clip\">background-clip</a> / <a href=\"https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html\">fx blur css filter</a> / <a href=\"http://dropshado.ws/post/1015351370/webkit-line-clamp\">-webkit-line-clamp</a> / <a href=\"https://developer.mozilla.org/en/CSS/text-overflow\">text-overflow</a> / <a href=\"https://developer.mozilla.org/En/CSS/Box-sizing\">box-sizing</a> / <a href=\"https://developer.mozilla.org/en/CSS3_Columns\">CSS columns</a></li>\n                <li><code>history.pushState()</code>, HTML5 input <code>checkValidity()</code>, <code>getClientRects</code> / <code>getBoundingClientRect</code>, WebKit's <a href=\"http://developer.apple.com/library/safari/#documentation/DataManagement/Reference/DOMWindowAdditionsReference/DOMWindowAdditions/DOMWindowAdditions.html\">ConvertPointFromPageToNode</a>\n                <li><a href=\"http://www.w3.org/TR/css3-gcpm/\">CSS Generated Content for Paged Media Module (GCPM)</a>\n                <li>Differences between <code>word-wrap</code>, <code>word-break</code>, and <code>white-space</code>\n                <li>Harmony features like <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:let\">let</a> / <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:block_scoped_bindings\">block-scoped bindings</a> / block functions /  <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:destructuring\">destructuring</a> / <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:rest_parameters\">rest parameters</a> / <a href=\"http://wiki.ecmascript.org/doku.php?id=harmony:parameter_default_values\">default param values</a>.\n                <li><a href=\"http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html\">Web Components Explained (very early draft)</a>\n\n                <li><strong>Qualquer funcionalidade destas apresentações:</strong>\n                  <ul>\n                    <li><a href=\"http://vimeo.com/32135328\">The Future of CSS</a> <span>- Tab Atkins sobre o que esperar do CSS no futuro.</span>\n                    <li><a href=\"http://infrequently.org/11/fronteers/fronteers.html\">Data, Semantics, and the Process of Progress </a> <span>- evolução dos navegadores, Component Model, MDV</span>\n                    <li><a href=\"http://infrequently.org/11/ldnjs/ldnjs.html\">[JS|DOM].next()</a> <span>- Alex Russell sobre a próxima versão do ECMAScript.</span>\n                    <li><a href=\"http://lea.verou.me/css3-secrets/\">CSS3 Secrets</a> <span>- uma apresentação interativa sobre o futuro das funcionalidades avançadas do CSS3.</span>\n                    <li><a href=\"http://nimbu.in/w3conf/\">The Future of Layouts in CSS</a> <span>- como especificações emergentes irão adicionar controle de layout apropriado ao CSS</span>\n                    <li><a href=\"http://mezzoblue.com/presentations/2011/fowd/FOWD.pdf\">The Future of CSS</a> <span>- uma visão geral de algumas funcionalidades CSS que estão surgindo.</span>\n\n                </ul>\n              </ul>\n\n            </div>\n            <div class=\"col-b\">\n\t          <section class=\"getinvolved\">\n                <h2 class=\"subhed\">Explore o desconhecido!</h2>\n                <div class=\"task\" data-hashtag=\"#explore\">\n                  <p>Vá em frente! A única forma de levar a web adiante é ir fundo e usar as funcionalidades e APIs avançadas. Divirta-se - nós sabemos que você irá!</p>\n                  <a href=\"#\" class=\"pledge\">Sim, eu quero fazer parte!</a>\n                  <div class=\"pledges\"><p>Veja outras pessoas que também estão interessadas:</p></div>\n                </div>\n             </section>\n          </div>\n        </section>\n\n\n        <section id=\"write\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">Escreva</h1>\n            <p>Publique sobre o que você aprender e não tenha medo de cometer enganos. Escreva em seu blog pessoal e mantenha seus posts atualizados. Certifique-se de escrever do seu jeito! Tenha em mente que você não precisa ser uma autoridade absoluta sobre um assunto para escrever a respeito de algo! Sempre faça perguntas e estimule discussões. Raramente há uma pergunta errada ou resposta errada.</p>\n\n            <p>Ensinar é uma ótima forma de aprender também. Então, mesmo que você esteja dando seus primeiros passos em uma área, você estará se ajudando escrevendo a respeito. Você sempre pode perguntar a um mentor ou amigo por uma opinião técnica. (Addy fez isso com aplomb.)</p>\n\n            <h2 id=\"what_should_you_start_to_learn_about\" class=\"subhed\">O que seria legal escrever a respeito?</h2>\n\n            <p>Algo que você pode ensinar aos outros! Veja algumas idéias:</p>\n\n            <ul>\n                <li>Por que os elementos <code>&lt;br&gt;</code> e <code>&lt;hr&gt;</code> (ou qualquer elemento) existem?</li>\n                <li>Como criar uma apresentação com o mínimo de código?</li>\n                <li>O que é o DOM? Por que ele existe?</li>\n                <li>Verifique como os navegadores implementam uma propriedade específica e compare com a especificação.</li>\n                <li>Como um website popular implementou sua página inicial (e sugestões de melhoras).</li>\n                <li>Como você corrigiria as falhas de um website popular (tempo  de carregamento grande, JS inválido, etc.).</li>\n                <li>Pegue uma demonstração prática e torne-a em algo diferente (ou utilize na prática).</li>\n                <li>Faça um sumário das idéias que circundam a web ultimamente.</li>\n                <li>Sua experiência contribuindo a um projeto open-source.</li>\n                <li>Como pré-processadores CSS podem levar a códigos cumpridos ou ruins se não forem gerenciados corretamente.</li>\n                <li>Se sua língua nativa não é o Inglês:\n                <ul class=\"resources\">\n                  <li>Traduza alguns sites populares de escritores em Inglês.</li>\n                  <li>Elabore sobre algumas funcionalidades das especificações.</li>\n                </ul>\n              </li>\n            </ul>\n          </div>\n          <div class=\"col-b\">\n            <section class=\"getinvolved\">\n              <h2 class=\"subhed\">Redija!</h2>\n              <div class=\"task\" data-hashtag=\"#write\">\n                <p>Não importa quantos seguidores no twitter ou watchers no github você tem - escreva sobre o que você aprendeu!</p>\n                <a href=\"#\" class=\"pledge\">Sim, eu quero fazer parte!</a>\n                <div class=\"pledges\"><p>Veja outras pessoas que também estão interessadas:</p></div>\n              </div>\n            </section>\n          </div>\n        </section>\n        <section id=\"filebugs\" class=\"col-ab\">\n          <div class=\"col-a\">\n            <h1 class=\"hed\">Reporte bugs</h1>\n            <p>De verdade, todos os criadores de navegadores ficariam muito mais felizes se você reportasse os bugs que encontrou do que xingar muito no twitter. =D</p>\n            <ul>\n              <li><a href=\"http://coding.smashingmagazine.com/2011/09/07/help-the-community-report-browser-bugs/\">Help the Community: Report Browser Bugs</a> por Lea Verou</li>\n              <li><a href=\"http://ejohn.org/blog/a-web-developers-responsibility/\">A Web Developer&#8217;s Responsibility</a> por John Resig</li>\n              <li><a href=\"http://a11ybugs.org/\">Help prioritize browser accessibility bugs</a> por Vlad Alexander</li>\n              <li>\n                <p>Rastreador de problemas de navegadores - procure bugs existentes ou reporte novos:</p>\n                <ul class=\"resources\">\n                  <li><a href=\"https://bugzilla.mozilla.org/\">Mozilla's bugzilla</a></li>\n                  <li><a href=\"https://bugs.webkit.org/\">WebKit bugs</a></li>\n                  <li><a href=\"http://crbug.com/\">Chrome bugs</a></li>\n                  <li><a href=\"http://www.opera.com/support/bugs/\">Opera bugs</a></li>\n                  <li><a href=\"https://connect.microsoft.com/site/sitehome.aspx?SiteID=136\">Help IE</a></li>\n                </ul>\n              </li>\n            </ul>\n          </div>\n          <div class=\"col-b\">\n            <section class=\"getinvolved\">\n              <h2 class=\"subhed\">Zunindo!</h2>\n              <div class=\"task\" data-hashtag=\"#filebugs\">\n                <p>Esta é a forma mais rápida de melhorar os navegadores - reportando e corrigindo bugs. Leva apenas alguns momentos, e qualquer um pode fazer.</p>\n                <a href=\"#\" class=\"pledge\">Sim, eu quero fazer parte!</a>\n                <div class=\"pledges\"><p>Veja outras pessoas que também estão interessadas:</p></div>\n              </div>\n            </section>\n          </div>\n        </section>\n    </article>\n    <article class=\"section\">\n      <div class=\"standout\" id=virtuoso>\n        <h1 class=\"hed\">Garoto pródigo!</h1>\n        <h2 class=\"subhed\">Você já chegou longe; é evidente que você sabe das coisas! Podemos sugerir algumas coisas?</h2>\n      </div>\n      <section id=\"hack\" class=\"col-ab\">\n        <div class=\"col-a\">\n          <h1 class=\"hed\">Hackeie!</h1>\n          <p>Leve a web aos limites! Hackeie do CSS, HTMl avançado e Javascript. Hackeie do sistema de renderização dos navegadores. Faça Fork em repositórios do github, escave pelo código, e mantenha-se aprendendo. Vamos fazer a web ainda mais incrível. Há tantos caminhos:</p>\n          <h2 id=\"contribute_to_browsers\" class=\"subhed\">Contribua para os navegadores</h2>\n          <ul>\n            <li>Ajude a construir ferramentas de desenvolvedor como <a href=\"http://trac.webkit.org/wiki/WebInspector\">WebKit Inspector</a> e <a href=\"https://bitbucket.org/scope/dragonfly-stp-1/\">Dragonfly</a>.\n            Eles são escritos em HTML, CSS e JS, e você não precisa ser um programador C++ para contribuir.\n            Escreva patches!</li>\n            <li><a href=\"https://developer.mozilla.org/en/Gecko_BugAThon\">Reduza os casos de teste da Mozilla</a></li>\n            <li><i>Hackeie</i> no Gecko\n              <ul>\n                <li>Leia o guia do desenvolvedor de <a href=\"https://developer.mozilla.org/En/Developer_Guide\">iniciando desenvolvimento com Gecko</a>.\n                <li>Uma <a href=\"https://bugzilla.mozilla.org/buglist.cgi?quicksearch=%22[mentor%3D%22&list_id=1800469\">lista de &#8220;bons primeiros bugs&#8221; para Firefox/Gecko</a>\n                <li>Faça parte dos canais #introduction e #developers no <a href=\"#mozilla_irc\">servidor IRC da Mozilla</a>\n              </ul>\n            <li><i>Hackeie</i> no Webkit\n              <ul>\n                <li><a href=\"http://dev.chromium.org/developers/contributing-to-webkit\">Guia do Google sobre como contribuir com o WebKit</a>\n              </ul>\n          </ul>\n\n          <h2 id=\"contribute_to_testsuites\" class=\"subhed\">Ajude nas Test Suites</h2>\n\n          <p>Testes são fundamentais para padrões e navegadores. Eles garantem que tudo funcione de forma consistente entre navegadores. Agora mesmo, a test suite da W3C está longe dos testes que deveriam ter. Testes são escritos na linguagem dos desenvolvedores: HTML, CSS, e JavaScript. </p>\n\n          <ul>\n            <li>Dê uma olhada em\n              <a href=\"http://www.w3.org/2008/webapps/wiki/Testing\">test suite de webapps da w3c</a>, a\n              <a href=\"http://www.w3.org/html/wg/wiki/Testing\">test suite para HTML da w3c</a>,\n              and the <a href=\"http://wiki.csswg.org/test\">test suite do CSSWG</a>.\n            </li>\n<!-- missing -->            <li>Dê uma olhada em <a href=\"http://www.w3.org/html/wg/wiki/Testing#New_tests\">turbinando testes existentes</a> para a suite de testes W3C.</li>\n            <li>Turbine o <a href=\"http://trac.webkit.org/browser/trunk/LayoutTests\">WebKit&#8217;s LayoutTests</a>. <span>Veja também a <a href=\"http://www.webkit.org/blog/1452/layout-tests-theory/\">teoria dos LayoutTests</a> & <a href=\"http://www.webkit.org/blog/1456/layout-tests-practice/\">prática</a>.</span></li>\n            <li>Turbine <a href=\"https://developer.mozilla.org/en/Mochitest\">Mozilla&#8217;s Mochitests</a>.</li>\n            <li>Entre pra conversa em  <a href=\"http://lists.w3.org/Archives/Public/public-webapps-testsuite/\">public-webapps-testsuite</a>, <a href=\"http://lists.w3.org/Archives/Public/public-html-testsuite/\">public-html-testsuite</a>, e <a href=\"http://lists.w3.org/Archives/Public/public-css-testsuite/\">public-css-testsuite</a>.</li>\n            <li>Contribua para o áudio no HTML5 em <a href=\"http://areweplayingyet.org\">the AreWePlayingYet? test suite</a>.</li>\n          </ul>\n\n\n          <h2 id=\"contribute_to_specs\" class=\"subhed\">Contribua com as especificações</h2>\n          <ul>\n            <li>Opine sobre bugs existentes no <a href=\"http://www.w3.org/Bugs/Public/\">W3C bugzilla</a> <span>- e aprenda as <a href=\"http://wiki.whatwg.org/wiki/Bugzilla_conventions\">Bugzilla conventions</a>.</span>\n            <li>Participe das discussões do <a href=\"http://www.whatwg.org/mailing-list\">WHATWG</a> / <a href=\"http://lists.w3.org/Archives/Public/public-webapps/\">public-webapps</a> / <a href=\"http://lists.w3.org/Archives/Public/www-style/\">www-style</a> / <a href=\"http://lists.w3.org/Archives/Public/public-fx/\">public-fx</a>.</li>\n            <li><a href=\"http://dev.chromium.org/developers/how-tos/make-a-web-standards-proposal\">Faça uma proposta web-standards</a>. <span>(este guia ensina como!)</span>\n            <li><a href=\"http://wiki.whatwg.org/wiki/How_to_write_a_spec\">Escreva especificações!</a> <span>certamente precisamos de mais escritores.</span></li>\n          </ul>\n          <h2 id=\"contribute_to_validators\" class=\"subhed\">Contribua para os validadores</h2>\n          <ul>\n            <li>\n              <a href=\"http://validator.nu/\">HTML Validator</a> <span>anda precisando de amor, dê uma olhada em <a href=\"https://github.com/paulirish/lazyweb-requests/issues/18\">lazyweb-reqs/18</a></span>\n            <li>\n              <a href=\"http://lists.w3.org/Archives/Public/www-validator-css/\">CSS Validator</a> <span>sempre exige carinho. Dê uma olhada nas listas de discussão!</span>\n            <li>\n              <a href=\"https://bitbucket.org/annevk/webvtt\">WebVTT</a> <span>um formato de legendas para vídeos, uma área ativa de interesse para padronização</span>\n            </ul>\n\n        <h2 id=\"contribute_to_projects\" class=\"subhed\">Ajude em projetos</h2>\n        <ul>\n          <li>\n          <a href=\"https://github.com/h5bp/lazyweb-requests/issues/\">Lazyweb Requests</a> <span>tem algumas idéis de projetos incríveis propostas por pessoas que adorariam ver suas idéias indo adiante.</span>\n          </li>\n        </ul>\n        </div>\n        <div class=\"col-b\">\n          <section class=\"getinvolved\">\n            <h2 class=\"subhed\">Só nas mutretas!</h2>\n            <div class=\"task\" data-hashtag=\"#hack\">\n              <p>Faça algo!. Experimente, faça fork em repositórios, cavuque código. Contribua para os navegadores, especificações, validadores, ou excelentes <a href=\"#open_source_projects_worth_your_time\">projetos open-source</a>!</p>\n              <a href=\"#\" class=\"pledge\">Sim, eu quero fazer parte!</a>\n              <div class=\"pledges\"><p>Veja outras pessoas que também estão interessadas:</p></div>\n            </div>\n          </section>\n        </div>\n      </section>\n    </article>\n\n\n\n    <footer class=\"doc\">\n\n      <p class=\"subhed summary\">\n        Você tem o poder de fazer a web ser incrível, do jeitinho que você quer! Criadores de navegadores, padronizadores e criadores de bibliotecas estão frequentemente procurando pela sua voz e sua contribuição. <br>Juntos conseguimos levar a web adiante.\n      </p>\n\n      <img src=\"../img/pugerton.png\" alt=\"Pugerton\">\n\n      <p class=\"subhed\">Feito com amor e lágrimas por</p>\n\n      <ul class=\"builders\">\n          <li><a href=\"https://twitter.com/wilto\"><img src=\"https://pbs.twimg.com/profile_images/477441227986444289/KHCUqTis_normal.png\" alt=\"Mat Marquis\"> <b>Mat</b> Marquis</a>\n          <li><a href=\"https://twitter.com/aaronforsander\"><img src=\"https://pbs.twimg.com/profile_images/461528075788763138/c7ONSIRm_normal.jpeg\" alt=\"Aaron Forsander\"> <b>Aaron</b> Forsander</a>\n          <li><a href=\"https://twitter.com/connor\"><img src=\"https://pbs.twimg.com/profile_images/526185574039031808/IpDbRAX5_normal.jpeg\" alt=\"Connor Montgomery\"> <b>Connor Montgomery</b></a>\n          <li><a href=\"https://twitter.com/paul_irish\"><img src=\"https://pbs.twimg.com/profile_images/420826194083213312/CP1RmLa3_normal.jpeg\" alt=\"Paul Irish\"> <b>Paul</b> Irish</a>\n          <li><a href=\"https://twitter.com/divya\"><img src=\"https://pbs.twimg.com/profile_images/550530231853776897/kni4F8oM_normal.png\" alt=\"Diviya Manian\"> <b>Divya</b> Manian</a>\n          <li><a href=\"https://twitter.com/necolas\"><img src=\"https://pbs.twimg.com/profile_images/529444560179449857/eKdCJhvp_normal.jpeg\" alt=\"Nicolas Gallagher\"> <b>Nicolas</b> Gallagher</a>\n          <li><a href=\"https://twitter.com/addyosmani\"><img src=\"https://pbs.twimg.com/profile_images/422476220442234880/jlx9HMtr_normal.jpeg\" alt=\"Addy Osmani\"> <b>Addy</b> Osmani</a>\n      </ul>\n      <p class=\"others\">& <a href=\"https://github.com/h5bp/movethewebforward/contributors\"><span>todas essas pessoas incríveis</span>.</a></p>\n      <p>Dinos por <a href=\"http://dribbble.com/deathbearbrown\">Sue Lockwood</a> • <a href=\"https://github.com/h5bp/movethewebforward\">Contribua neste projeto!</a></p>\n    </footer>\n    <script>\n        window._gaq=[['_setAccount','UA-17904194-2'],['_trackPageview']];\n        (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];\n        g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';\n        s.parentNode.insertBefore(g,s)}(document,'script'));\n    </script>\n</body>\n</html>\n"
  },
  {
    "path": "pull.sh",
    "content": "#!/usr/bin/env bash\n\ngit reset --hard HEAD\n\ngit pull origin master\n\nphp avatars.php\n\n\n\n"
  },
  {
    "path": "push.sh",
    "content": "#!/usr/bin/env bash\n\ngit push origin master\n\ngit push -f origin origin/master:gh-pages\n\n"
  },
  {
    "path": "robots.txt",
    "content": "# www.robotstxt.org/\n# www.google.com/support/webmasters/bin/answer.py?hl=en&answer=156449\n\nUser-agent: *\nDisallow:\n"
  }
]